]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Fixed many issues with q2bsp support, it now works properly.
[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 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47 static qboolean r_gpuskeletal;
48
49 //
50 // screen size info
51 //
52 r_refdef_t r_refdef;
53
54 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!"};
55 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!"};
56 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
57 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
58 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)"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
60 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"};
61 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"};
62 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"};
63 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"};
64 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"};
65 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"};
66
67 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
68 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"};
69 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
70 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)"};
71 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
72
73 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"};
74 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
75 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
76 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
77 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
78 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
79 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
80 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"};
81 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"};
82 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"};
83 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
84 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
85 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)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 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"};
89 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"};
90 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
91 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"};
92 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"};
93 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"};
94 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
95 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
96 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
97 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
98 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
99 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
100 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
101 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)"};
102 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)"};
103 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
104 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
105 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
106 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
107 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
108
109 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
110 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
111 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
112
113 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
114 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
115 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
116 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."};
117 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
118 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
119 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
120 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."};
121 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
122 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
123 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
124 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."};
125 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
126 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"};
127 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"};
128 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
130 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
131 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
132 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
133 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"};
134 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
135 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
136 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
137 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
138 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
139
140 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
141 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
142 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
143 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
144 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
145 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
146 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
147 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
148
149 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)"};
150 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"};
151
152 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
153 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
154 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
155
156 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"};
157 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"};
158 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"};
159 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
160 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
161 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"};
162 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)"};
163 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)"};
164 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
165
166 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
167 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)"};
168 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
169 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)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
171 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)"};
172 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)"};
173 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
174 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"};
175 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."};
176 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183 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)"};
184 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)"};
185
186 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)"};
187 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
188 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"};
189 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
190 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
191 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
192 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"};
193 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"};
194 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)"};
195
196 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
197 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
198 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
199 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
200
201 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
202 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
203
204 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
205 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
206 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
207 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
208 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
209 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
210
211 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
212 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
213 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
214 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
215 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
218 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
219 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
220 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
221
222 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"};
223
224 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"};
225
226 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
227
228 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
229
230 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)"};
231 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)"};
232 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
234
235 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
236 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"};
237
238 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."};
239
240 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)"};
241 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
242 {
243         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
244         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
245         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
246         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
247 };
248
249 extern cvar_t v_glslgamma;
250 extern cvar_t v_glslgamma_2d;
251
252 extern qboolean v_flipped_state;
253
254 r_framebufferstate_t r_fb;
255
256 /// shadow volume bsp struct with automatically growing nodes buffer
257 svbsp_t r_svbsp;
258
259 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
260
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
274
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
277 {
278         char basename[64];
279         rtexture_t *texture;
280 }
281 cubemapinfo_t;
282
283 int r_texture_numcubemaps;
284 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
285
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
289
290 typedef struct r_qwskincache_s
291 {
292         char name[MAX_QPATH];
293         skinframe_t *skinframe;
294 }
295 r_qwskincache_t;
296
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
299
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
304 {
305         0, 0, 0,
306         1, 0, 0,
307         1, 1, 0,
308         0, 1, 0
309 };
310 const float r_d3dscreenvertex3f[12] =
311 {
312         0, 1, 0,
313         1, 1, 0,
314         1, 0, 0,
315         0, 0, 0
316 };
317
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
319 {
320         int i;
321         for (i = 0;i < verts;i++)
322         {
323                 out[0] = in[0] * r;
324                 out[1] = in[1] * g;
325                 out[2] = in[2] * b;
326                 out[3] = in[3];
327                 in += 4;
328                 out += 4;
329         }
330 }
331
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = r;
338                 out[1] = g;
339                 out[2] = b;
340                 out[3] = a;
341                 out += 4;
342         }
343 }
344
345 // FIXME: move this to client?
346 void FOG_clear(void)
347 {
348         if (gamemode == GAME_NEHAHRA)
349         {
350                 Cvar_Set("gl_fogenable", "0");
351                 Cvar_Set("gl_fogdensity", "0.2");
352                 Cvar_Set("gl_fogred", "0.3");
353                 Cvar_Set("gl_foggreen", "0.3");
354                 Cvar_Set("gl_fogblue", "0.3");
355         }
356         r_refdef.fog_density = 0;
357         r_refdef.fog_red = 0;
358         r_refdef.fog_green = 0;
359         r_refdef.fog_blue = 0;
360         r_refdef.fog_alpha = 1;
361         r_refdef.fog_start = 0;
362         r_refdef.fog_end = 16384;
363         r_refdef.fog_height = 1<<30;
364         r_refdef.fog_fadedepth = 128;
365         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
366 }
367
368 static void R_BuildBlankTextures(void)
369 {
370         unsigned char data[4];
371         data[2] = 128; // normal X
372         data[1] = 128; // normal Y
373         data[0] = 255; // normal Z
374         data[3] = 255; // height
375         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 255;
377         data[1] = 255;
378         data[2] = 255;
379         data[3] = 255;
380         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 128;
382         data[1] = 128;
383         data[2] = 128;
384         data[3] = 255;
385         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 0;
387         data[1] = 0;
388         data[2] = 0;
389         data[3] = 255;
390         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildNoTexture(void)
394 {
395         int x, y;
396         unsigned char pix[16][16][4];
397         // this makes a light grey/dark grey checkerboard texture
398         for (y = 0;y < 16;y++)
399         {
400                 for (x = 0;x < 16;x++)
401                 {
402                         if ((y < 8) ^ (x < 8))
403                         {
404                                 pix[y][x][0] = 128;
405                                 pix[y][x][1] = 128;
406                                 pix[y][x][2] = 128;
407                                 pix[y][x][3] = 255;
408                         }
409                         else
410                         {
411                                 pix[y][x][0] = 64;
412                                 pix[y][x][1] = 64;
413                                 pix[y][x][2] = 64;
414                                 pix[y][x][3] = 255;
415                         }
416                 }
417         }
418         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
419 }
420
421 static void R_BuildWhiteCube(void)
422 {
423         unsigned char data[6*1*1*4];
424         memset(data, 255, sizeof(data));
425         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
426 }
427
428 static void R_BuildNormalizationCube(void)
429 {
430         int x, y, side;
431         vec3_t v;
432         vec_t s, t, intensity;
433 #define NORMSIZE 64
434         unsigned char *data;
435         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436         for (side = 0;side < 6;side++)
437         {
438                 for (y = 0;y < NORMSIZE;y++)
439                 {
440                         for (x = 0;x < NORMSIZE;x++)
441                         {
442                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 switch(side)
445                                 {
446                                 default:
447                                 case 0:
448                                         v[0] = 1;
449                                         v[1] = -t;
450                                         v[2] = -s;
451                                         break;
452                                 case 1:
453                                         v[0] = -1;
454                                         v[1] = -t;
455                                         v[2] = s;
456                                         break;
457                                 case 2:
458                                         v[0] = s;
459                                         v[1] = 1;
460                                         v[2] = t;
461                                         break;
462                                 case 3:
463                                         v[0] = s;
464                                         v[1] = -1;
465                                         v[2] = -t;
466                                         break;
467                                 case 4:
468                                         v[0] = s;
469                                         v[1] = -t;
470                                         v[2] = 1;
471                                         break;
472                                 case 5:
473                                         v[0] = -s;
474                                         v[1] = -t;
475                                         v[2] = -1;
476                                         break;
477                                 }
478                                 intensity = 127.0f / sqrt(DotProduct(v, v));
479                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482                                 data[((side*64+y)*64+x)*4+3] = 255;
483                         }
484                 }
485         }
486         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
487         Mem_Free(data);
488 }
489
490 static void R_BuildFogTexture(void)
491 {
492         int x, b;
493 #define FOGWIDTH 256
494         unsigned char data1[FOGWIDTH][4];
495         //unsigned char data2[FOGWIDTH][4];
496         double d, r, alpha;
497
498         r_refdef.fogmasktable_start = r_refdef.fog_start;
499         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500         r_refdef.fogmasktable_range = r_refdef.fogrange;
501         r_refdef.fogmasktable_density = r_refdef.fog_density;
502
503         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505         {
506                 d = (x * r - r_refdef.fogmasktable_start);
507                 if(developer_extra.integer)
508                         Con_DPrintf("%f ", d);
509                 d = max(0, d);
510                 if (r_fog_exp2.integer)
511                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512                 else
513                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514                 if(developer_extra.integer)
515                         Con_DPrintf(" : %f ", alpha);
516                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517                 if(developer_extra.integer)
518                         Con_DPrintf(" = %f\n", alpha);
519                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
520         }
521
522         for (x = 0;x < FOGWIDTH;x++)
523         {
524                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
525                 data1[x][0] = b;
526                 data1[x][1] = b;
527                 data1[x][2] = b;
528                 data1[x][3] = 255;
529                 //data2[x][0] = 255 - b;
530                 //data2[x][1] = 255 - b;
531                 //data2[x][2] = 255 - b;
532                 //data2[x][3] = 255;
533         }
534         if (r_texture_fogattenuation)
535         {
536                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538         }
539         else
540         {
541                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
543         }
544 }
545
546 static void R_BuildFogHeightTexture(void)
547 {
548         unsigned char *inpixels;
549         int size;
550         int x;
551         int y;
552         int j;
553         float c[4];
554         float f;
555         inpixels = NULL;
556         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557         if (r_refdef.fogheighttexturename[0])
558                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
559         if (!inpixels)
560         {
561                 r_refdef.fog_height_tablesize = 0;
562                 if (r_texture_fogheighttexture)
563                         R_FreeTexture(r_texture_fogheighttexture);
564                 r_texture_fogheighttexture = NULL;
565                 if (r_refdef.fog_height_table2d)
566                         Mem_Free(r_refdef.fog_height_table2d);
567                 r_refdef.fog_height_table2d = NULL;
568                 if (r_refdef.fog_height_table1d)
569                         Mem_Free(r_refdef.fog_height_table1d);
570                 r_refdef.fog_height_table1d = NULL;
571                 return;
572         }
573         size = image_width;
574         r_refdef.fog_height_tablesize = size;
575         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578         Mem_Free(inpixels);
579         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
580         // average fog color table accounting for every fog layer between a point
581         // and the camera.  (Note: attenuation is handled separately!)
582         for (y = 0;y < size;y++)
583         {
584                 for (x = 0;x < size;x++)
585                 {
586                         Vector4Clear(c);
587                         f = 0;
588                         if (x < y)
589                         {
590                                 for (j = x;j <= y;j++)
591                                 {
592                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
593                                         f++;
594                                 }
595                         }
596                         else
597                         {
598                                 for (j = x;j >= y;j--)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         f = 1.0f / f;
605                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
609                 }
610         }
611         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
612 }
613
614 //=======================================================================================================================================================
615
616 static const char *builtinshaderstrings[] =
617 {
618 #include "shader_glsl.h"
619 0
620 };
621
622 const char *builtinhlslshaderstrings[] =
623 {
624 #include "shader_hlsl.h"
625 0
626 };
627
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
630
631 //=======================================================================================================================================================
632
633 typedef struct shaderpermutationinfo_s
634 {
635         const char *pretext;
636         const char *name;
637 }
638 shaderpermutationinfo_t;
639
640 typedef struct shadermodeinfo_s
641 {
642         const char *filename;
643         const char *pretext;
644         const char *name;
645 }
646 shadermodeinfo_t;
647
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {
651         {"#define USEDIFFUSE\n", " diffuse"},
652         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653         {"#define USEVIEWTINT\n", " viewtint"},
654         {"#define USECOLORMAPPING\n", " colormapping"},
655         {"#define USESATURATION\n", " saturation"},
656         {"#define USEFOGINSIDE\n", " foginside"},
657         {"#define USEFOGOUTSIDE\n", " fogoutside"},
658         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660         {"#define USEGAMMARAMPS\n", " gammaramps"},
661         {"#define USECUBEFILTER\n", " cubefilter"},
662         {"#define USEGLOW\n", " glow"},
663         {"#define USEBLOOM\n", " bloom"},
664         {"#define USESPECULAR\n", " specular"},
665         {"#define USEPOSTPROCESSING\n", " postprocessing"},
666         {"#define USEREFLECTION\n", " reflection"},
667         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
671         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673         {"#define USEALPHAKILL\n", " alphakill"},
674         {"#define USEREFLECTCUBE\n", " reflectcube"},
675         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676         {"#define USEBOUNCEGRID\n", " bouncegrid"},
677         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
678         {"#define USETRIPPY\n", " trippy"},
679         {"#define USEDEPTHRGB\n", " depthrgb"},
680         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
681         {"#define USESKELETAL\n", " skeletal"}
682 };
683
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
686 {
687         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
697         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
698         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
699         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
700         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
701         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
702         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
707 {
708         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
725 };
726
727 struct r_glsl_permutation_s;
728 typedef struct r_glsl_permutation_s
729 {
730         /// hash lookup data
731         struct r_glsl_permutation_s *hashnext;
732         unsigned int mode;
733         unsigned int permutation;
734
735         /// indicates if we have tried compiling this permutation already
736         qboolean compiled;
737         /// 0 if compilation failed
738         int program;
739         // texture units assigned to each detected uniform
740         int tex_Texture_First;
741         int tex_Texture_Second;
742         int tex_Texture_GammaRamps;
743         int tex_Texture_Normal;
744         int tex_Texture_Color;
745         int tex_Texture_Gloss;
746         int tex_Texture_Glow;
747         int tex_Texture_SecondaryNormal;
748         int tex_Texture_SecondaryColor;
749         int tex_Texture_SecondaryGloss;
750         int tex_Texture_SecondaryGlow;
751         int tex_Texture_Pants;
752         int tex_Texture_Shirt;
753         int tex_Texture_FogHeightTexture;
754         int tex_Texture_FogMask;
755         int tex_Texture_Lightmap;
756         int tex_Texture_Deluxemap;
757         int tex_Texture_Attenuation;
758         int tex_Texture_Cube;
759         int tex_Texture_Refraction;
760         int tex_Texture_Reflection;
761         int tex_Texture_ShadowMap2D;
762         int tex_Texture_CubeProjection;
763         int tex_Texture_ScreenNormalMap;
764         int tex_Texture_ScreenDiffuse;
765         int tex_Texture_ScreenSpecular;
766         int tex_Texture_ReflectMask;
767         int tex_Texture_ReflectCube;
768         int tex_Texture_BounceGrid;
769         /// locations of detected uniforms in program object, or -1 if not found
770         int loc_Texture_First;
771         int loc_Texture_Second;
772         int loc_Texture_GammaRamps;
773         int loc_Texture_Normal;
774         int loc_Texture_Color;
775         int loc_Texture_Gloss;
776         int loc_Texture_Glow;
777         int loc_Texture_SecondaryNormal;
778         int loc_Texture_SecondaryColor;
779         int loc_Texture_SecondaryGloss;
780         int loc_Texture_SecondaryGlow;
781         int loc_Texture_Pants;
782         int loc_Texture_Shirt;
783         int loc_Texture_FogHeightTexture;
784         int loc_Texture_FogMask;
785         int loc_Texture_Lightmap;
786         int loc_Texture_Deluxemap;
787         int loc_Texture_Attenuation;
788         int loc_Texture_Cube;
789         int loc_Texture_Refraction;
790         int loc_Texture_Reflection;
791         int loc_Texture_ShadowMap2D;
792         int loc_Texture_CubeProjection;
793         int loc_Texture_ScreenNormalMap;
794         int loc_Texture_ScreenDiffuse;
795         int loc_Texture_ScreenSpecular;
796         int loc_Texture_ReflectMask;
797         int loc_Texture_ReflectCube;
798         int loc_Texture_BounceGrid;
799         int loc_Alpha;
800         int loc_BloomBlur_Parameters;
801         int loc_ClientTime;
802         int loc_Color_Ambient;
803         int loc_Color_Diffuse;
804         int loc_Color_Specular;
805         int loc_Color_Glow;
806         int loc_Color_Pants;
807         int loc_Color_Shirt;
808         int loc_DeferredColor_Ambient;
809         int loc_DeferredColor_Diffuse;
810         int loc_DeferredColor_Specular;
811         int loc_DeferredMod_Diffuse;
812         int loc_DeferredMod_Specular;
813         int loc_DistortScaleRefractReflect;
814         int loc_EyePosition;
815         int loc_FogColor;
816         int loc_FogHeightFade;
817         int loc_FogPlane;
818         int loc_FogPlaneViewDist;
819         int loc_FogRangeRecip;
820         int loc_LightColor;
821         int loc_LightDir;
822         int loc_LightPosition;
823         int loc_OffsetMapping_ScaleSteps;
824         int loc_OffsetMapping_LodDistance;
825         int loc_OffsetMapping_Bias;
826         int loc_PixelSize;
827         int loc_ReflectColor;
828         int loc_ReflectFactor;
829         int loc_ReflectOffset;
830         int loc_RefractColor;
831         int loc_Saturation;
832         int loc_ScreenCenterRefractReflect;
833         int loc_ScreenScaleRefractReflect;
834         int loc_ScreenToDepth;
835         int loc_ShadowMap_Parameters;
836         int loc_ShadowMap_TextureScale;
837         int loc_SpecularPower;
838         int loc_Skeletal_Transform12;
839         int loc_UserVec1;
840         int loc_UserVec2;
841         int loc_UserVec3;
842         int loc_UserVec4;
843         int loc_ViewTintColor;
844         int loc_ViewToLight;
845         int loc_ModelToLight;
846         int loc_TexMatrix;
847         int loc_BackgroundTexMatrix;
848         int loc_ModelViewProjectionMatrix;
849         int loc_ModelViewMatrix;
850         int loc_PixelToScreenTexCoord;
851         int loc_ModelToReflectCube;
852         int loc_ShadowMapMatrix;
853         int loc_BloomColorSubtract;
854         int loc_NormalmapScrollBlend;
855         int loc_BounceGridMatrix;
856         int loc_BounceGridIntensity;
857         /// uniform block bindings
858         int ubibind_Skeletal_Transform12_UniformBlock;
859         /// uniform block indices
860         int ubiloc_Skeletal_Transform12_UniformBlock;
861 }
862 r_glsl_permutation_t;
863
864 #define SHADERPERMUTATION_HASHSIZE 256
865
866
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
869 enum
870 {
871         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
877         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
879         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
880         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
881         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
882         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
883         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
884         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
885 };
886 #define SHADERSTATICPARMS_COUNT 14
887
888 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
889 static int shaderstaticparms_count = 0;
890
891 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
892 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
893
894 extern qboolean r_shadow_shadowmapsampler;
895 extern int r_shadow_shadowmappcf;
896 qboolean R_CompileShader_CheckStaticParms(void)
897 {
898         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
899         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
900         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
901
902         // detect all
903         if (r_glsl_saturation_redcompensate.integer)
904                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
905         if (r_glsl_vertextextureblend_usebothalphas.integer)
906                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
907         if (r_shadow_glossexact.integer)
908                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
909         if (r_glsl_postprocess.integer)
910         {
911                 if (r_glsl_postprocess_uservec1_enable.integer)
912                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
913                 if (r_glsl_postprocess_uservec2_enable.integer)
914                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
915                 if (r_glsl_postprocess_uservec3_enable.integer)
916                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
917                 if (r_glsl_postprocess_uservec4_enable.integer)
918                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
919         }
920         if (r_fxaa.integer)
921                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
922         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
923                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
924
925         if (r_shadow_shadowmapsampler)
926                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
927         if (r_shadow_shadowmappcf > 1)
928                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
929         else if (r_shadow_shadowmappcf)
930                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
931         if (r_celshading.integer)
932                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
933         if (r_celoutlines.integer)
934                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
935
936         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
937 }
938
939 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
940         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
941                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
942         else \
943                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
944 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
945 {
946         shaderstaticparms_count = 0;
947
948         // emit all
949         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
950         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
951         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
952         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
953         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
954         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
955         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
956         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
957         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
958         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
959         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
960         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
961         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
962         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
963 }
964
965 /// information about each possible shader permutation
966 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
967 /// currently selected permutation
968 r_glsl_permutation_t *r_glsl_permutation;
969 /// storage for permutations linked in the hash table
970 memexpandablearray_t r_glsl_permutationarray;
971
972 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
973 {
974         //unsigned int hashdepth = 0;
975         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
976         r_glsl_permutation_t *p;
977         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
978         {
979                 if (p->mode == mode && p->permutation == permutation)
980                 {
981                         //if (hashdepth > 10)
982                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
983                         return p;
984                 }
985                 //hashdepth++;
986         }
987         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
988         p->mode = mode;
989         p->permutation = permutation;
990         p->hashnext = r_glsl_permutationhash[mode][hashindex];
991         r_glsl_permutationhash[mode][hashindex] = p;
992         //if (hashdepth > 10)
993         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
994         return p;
995 }
996
997 static char *R_ShaderStrCat(const char **strings)
998 {
999         char *string, *s;
1000         const char **p = strings;
1001         const char *t;
1002         size_t len = 0;
1003         for (p = strings;(t = *p);p++)
1004                 len += strlen(t);
1005         len++;
1006         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1007         len = 0;
1008         for (p = strings;(t = *p);p++)
1009         {
1010                 len = strlen(t);
1011                 memcpy(s, t, len);
1012                 s += len;
1013         }
1014         *s = 0;
1015         return string;
1016 }
1017
1018 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1019 {
1020         char *shaderstring;
1021         if (!filename || !filename[0])
1022                 return NULL;
1023         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1024         if (!strcmp(filename, "glsl/default.glsl"))
1025         {
1026                 if (builtinonly)
1027                         return R_ShaderStrCat(builtinshaderstrings);
1028                 if (!glslshaderstring)
1029                 {
1030                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1031                         if (glslshaderstring)
1032                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1033                         else
1034                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1035                 }
1036                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1037                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1038                 return shaderstring;
1039         }
1040         if (!strcmp(filename, "hlsl/default.hlsl"))
1041         {
1042                 if (builtinonly)
1043                         return R_ShaderStrCat(builtinhlslshaderstrings);
1044                 if (!hlslshaderstring)
1045                 {
1046                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1047                         if (hlslshaderstring)
1048                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1049                         else
1050                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1051                 }
1052                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1053                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1054                 return shaderstring;
1055         }
1056         // we don't have builtin strings for any other files
1057         if (builtinonly)
1058                 return NULL;
1059         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1060         if (shaderstring)
1061         {
1062                 if (printfromdisknotice)
1063                         Con_DPrintf("from disk %s... ", filename);
1064                 return shaderstring;
1065         }
1066         return shaderstring;
1067 }
1068
1069 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1070 {
1071         int i;
1072         int ubibind;
1073         int sampler;
1074         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1075         char *sourcestring;
1076         char permutationname[256];
1077         int vertstrings_count = 0;
1078         int geomstrings_count = 0;
1079         int fragstrings_count = 0;
1080         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1081         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1082         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1083
1084         if (p->compiled)
1085                 return;
1086         p->compiled = true;
1087         p->program = 0;
1088
1089         permutationname[0] = 0;
1090         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1091
1092         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1093
1094         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1095         if(vid.support.glshaderversion >= 140)
1096         {
1097                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1098                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1099                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1100                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1101                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1102                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1103         }
1104         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1105         else if(vid.support.glshaderversion >= 130)
1106         {
1107                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1108                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1109                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1110                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1111                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1112                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1113         }
1114
1115         // the first pretext is which type of shader to compile as
1116         // (later these will all be bound together as a program object)
1117         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1118         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1119         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1120
1121         // the second pretext is the mode (for example a light source)
1122         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1123         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1124         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1125         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1126
1127         // now add all the permutation pretexts
1128         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1129         {
1130                 if (permutation & (1<<i))
1131                 {
1132                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1133                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1134                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1135                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1136                 }
1137                 else
1138                 {
1139                         // keep line numbers correct
1140                         vertstrings_list[vertstrings_count++] = "\n";
1141                         geomstrings_list[geomstrings_count++] = "\n";
1142                         fragstrings_list[fragstrings_count++] = "\n";
1143                 }
1144         }
1145
1146         // add static parms
1147         R_CompileShader_AddStaticParms(mode, permutation);
1148         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1149         vertstrings_count += shaderstaticparms_count;
1150         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1151         geomstrings_count += shaderstaticparms_count;
1152         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1153         fragstrings_count += shaderstaticparms_count;
1154
1155         // now append the shader text itself
1156         vertstrings_list[vertstrings_count++] = sourcestring;
1157         geomstrings_list[geomstrings_count++] = sourcestring;
1158         fragstrings_list[fragstrings_count++] = sourcestring;
1159
1160         // compile the shader program
1161         if (vertstrings_count + geomstrings_count + fragstrings_count)
1162                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1163         if (p->program)
1164         {
1165                 CHECKGLERROR
1166                 qglUseProgram(p->program);CHECKGLERROR
1167                 // look up all the uniform variable names we care about, so we don't
1168                 // have to look them up every time we set them
1169
1170 #if 0
1171                 // debugging aid
1172                 {
1173                         GLint activeuniformindex = 0;
1174                         GLint numactiveuniforms = 0;
1175                         char uniformname[128];
1176                         GLsizei uniformnamelength = 0;
1177                         GLint uniformsize = 0;
1178                         GLenum uniformtype = 0;
1179                         memset(uniformname, 0, sizeof(uniformname));
1180                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1181                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1182                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1183                         {
1184                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1185                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1186                         }
1187                 }
1188 #endif
1189
1190                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1191                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1192                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1193                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1194                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1195                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1196                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1197                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1198                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1199                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1200                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1201                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1202                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1203                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1204                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1205                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1206                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1207                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1208                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1209                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1210                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1211                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1212                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1213                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1214                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1215                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1216                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1217                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1218                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1219                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1220                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1221                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1222                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1223                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1224                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1225                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1226                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1227                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1228                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1229                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1230                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1231                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1232                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1233                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1234                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1235                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1236                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1237                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1238                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1239                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1240                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1241                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1242                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1243                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1244                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1245                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1246                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1247                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1248                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1249                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1250                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1251                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1252                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1253                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1254                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1255                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1256                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1257                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1258                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1259                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1260                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1261                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1262                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1263                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1264                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1265                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1266                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1267                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1268                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1269                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1270                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1271                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1272                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1273                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1274                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1275                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1276                 // initialize the samplers to refer to the texture units we use
1277                 p->tex_Texture_First = -1;
1278                 p->tex_Texture_Second = -1;
1279                 p->tex_Texture_GammaRamps = -1;
1280                 p->tex_Texture_Normal = -1;
1281                 p->tex_Texture_Color = -1;
1282                 p->tex_Texture_Gloss = -1;
1283                 p->tex_Texture_Glow = -1;
1284                 p->tex_Texture_SecondaryNormal = -1;
1285                 p->tex_Texture_SecondaryColor = -1;
1286                 p->tex_Texture_SecondaryGloss = -1;
1287                 p->tex_Texture_SecondaryGlow = -1;
1288                 p->tex_Texture_Pants = -1;
1289                 p->tex_Texture_Shirt = -1;
1290                 p->tex_Texture_FogHeightTexture = -1;
1291                 p->tex_Texture_FogMask = -1;
1292                 p->tex_Texture_Lightmap = -1;
1293                 p->tex_Texture_Deluxemap = -1;
1294                 p->tex_Texture_Attenuation = -1;
1295                 p->tex_Texture_Cube = -1;
1296                 p->tex_Texture_Refraction = -1;
1297                 p->tex_Texture_Reflection = -1;
1298                 p->tex_Texture_ShadowMap2D = -1;
1299                 p->tex_Texture_CubeProjection = -1;
1300                 p->tex_Texture_ScreenNormalMap = -1;
1301                 p->tex_Texture_ScreenDiffuse = -1;
1302                 p->tex_Texture_ScreenSpecular = -1;
1303                 p->tex_Texture_ReflectMask = -1;
1304                 p->tex_Texture_ReflectCube = -1;
1305                 p->tex_Texture_BounceGrid = -1;
1306                 // bind the texture samplers in use
1307                 sampler = 0;
1308                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1309                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1310                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1311                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1312                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1313                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1314                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1315                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1316                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1317                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1318                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1319                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1320                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1321                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1322                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1323                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1324                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1325                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1326                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1327                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1328                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1329                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1330                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1331                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1332                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1333                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1334                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1335                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1336                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1337                 // get the uniform block indices so we can bind them
1338 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1339                 if (vid.support.arb_uniform_buffer_object)
1340                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1341                 else
1342 #endif
1343                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1344                 // clear the uniform block bindings
1345                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1346                 // bind the uniform blocks in use
1347                 ubibind = 0;
1348 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1349                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1350 #endif
1351                 // we're done compiling and setting up the shader, at least until it is used
1352                 CHECKGLERROR
1353                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1354         }
1355         else
1356                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1357
1358         // free the strings
1359         if (sourcestring)
1360                 Mem_Free(sourcestring);
1361 }
1362
1363 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1364 {
1365         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1366         if (r_glsl_permutation != perm)
1367         {
1368                 r_glsl_permutation = perm;
1369                 if (!r_glsl_permutation->program)
1370                 {
1371                         if (!r_glsl_permutation->compiled)
1372                         {
1373                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1374                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1375                         }
1376                         if (!r_glsl_permutation->program)
1377                         {
1378                                 // remove features until we find a valid permutation
1379                                 int i;
1380                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1381                                 {
1382                                         // reduce i more quickly whenever it would not remove any bits
1383                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1384                                         if (!(permutation & j))
1385                                                 continue;
1386                                         permutation -= j;
1387                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1388                                         if (!r_glsl_permutation->compiled)
1389                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1390                                         if (r_glsl_permutation->program)
1391                                                 break;
1392                                 }
1393                                 if (i >= SHADERPERMUTATION_COUNT)
1394                                 {
1395                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1396                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1397                                         qglUseProgram(0);CHECKGLERROR
1398                                         return; // no bit left to clear, entire mode is broken
1399                                 }
1400                         }
1401                 }
1402                 CHECKGLERROR
1403                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1404         }
1405         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1406         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1407         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1408         CHECKGLERROR
1409 }
1410
1411 #ifdef SUPPORTD3D
1412
1413 #ifdef SUPPORTD3D
1414 #include <d3d9.h>
1415 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1416 extern D3DCAPS9 vid_d3d9caps;
1417 #endif
1418
1419 struct r_hlsl_permutation_s;
1420 typedef struct r_hlsl_permutation_s
1421 {
1422         /// hash lookup data
1423         struct r_hlsl_permutation_s *hashnext;
1424         unsigned int mode;
1425         unsigned int permutation;
1426
1427         /// indicates if we have tried compiling this permutation already
1428         qboolean compiled;
1429         /// NULL if compilation failed
1430         IDirect3DVertexShader9 *vertexshader;
1431         IDirect3DPixelShader9 *pixelshader;
1432 }
1433 r_hlsl_permutation_t;
1434
1435 typedef enum D3DVSREGISTER_e
1436 {
1437         D3DVSREGISTER_TexMatrix = 0, // float4x4
1438         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1439         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1440         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1441         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1442         D3DVSREGISTER_ModelToLight = 20, // float4x4
1443         D3DVSREGISTER_EyePosition = 24,
1444         D3DVSREGISTER_FogPlane = 25,
1445         D3DVSREGISTER_LightDir = 26,
1446         D3DVSREGISTER_LightPosition = 27,
1447 }
1448 D3DVSREGISTER_t;
1449
1450 typedef enum D3DPSREGISTER_e
1451 {
1452         D3DPSREGISTER_Alpha = 0,
1453         D3DPSREGISTER_BloomBlur_Parameters = 1,
1454         D3DPSREGISTER_ClientTime = 2,
1455         D3DPSREGISTER_Color_Ambient = 3,
1456         D3DPSREGISTER_Color_Diffuse = 4,
1457         D3DPSREGISTER_Color_Specular = 5,
1458         D3DPSREGISTER_Color_Glow = 6,
1459         D3DPSREGISTER_Color_Pants = 7,
1460         D3DPSREGISTER_Color_Shirt = 8,
1461         D3DPSREGISTER_DeferredColor_Ambient = 9,
1462         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1463         D3DPSREGISTER_DeferredColor_Specular = 11,
1464         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1465         D3DPSREGISTER_DeferredMod_Specular = 13,
1466         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1467         D3DPSREGISTER_EyePosition = 15, // unused
1468         D3DPSREGISTER_FogColor = 16,
1469         D3DPSREGISTER_FogHeightFade = 17,
1470         D3DPSREGISTER_FogPlane = 18,
1471         D3DPSREGISTER_FogPlaneViewDist = 19,
1472         D3DPSREGISTER_FogRangeRecip = 20,
1473         D3DPSREGISTER_LightColor = 21,
1474         D3DPSREGISTER_LightDir = 22, // unused
1475         D3DPSREGISTER_LightPosition = 23,
1476         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1477         D3DPSREGISTER_PixelSize = 25,
1478         D3DPSREGISTER_ReflectColor = 26,
1479         D3DPSREGISTER_ReflectFactor = 27,
1480         D3DPSREGISTER_ReflectOffset = 28,
1481         D3DPSREGISTER_RefractColor = 29,
1482         D3DPSREGISTER_Saturation = 30,
1483         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1484         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1485         D3DPSREGISTER_ScreenToDepth = 33,
1486         D3DPSREGISTER_ShadowMap_Parameters = 34,
1487         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1488         D3DPSREGISTER_SpecularPower = 36,
1489         D3DPSREGISTER_UserVec1 = 37,
1490         D3DPSREGISTER_UserVec2 = 38,
1491         D3DPSREGISTER_UserVec3 = 39,
1492         D3DPSREGISTER_UserVec4 = 40,
1493         D3DPSREGISTER_ViewTintColor = 41,
1494         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1495         D3DPSREGISTER_BloomColorSubtract = 43,
1496         D3DPSREGISTER_ViewToLight = 44, // float4x4
1497         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1498         D3DPSREGISTER_NormalmapScrollBlend = 52,
1499         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1500         D3DPSREGISTER_OffsetMapping_Bias = 54,
1501         // next at 54
1502 }
1503 D3DPSREGISTER_t;
1504
1505 /// information about each possible shader permutation
1506 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1507 /// currently selected permutation
1508 r_hlsl_permutation_t *r_hlsl_permutation;
1509 /// storage for permutations linked in the hash table
1510 memexpandablearray_t r_hlsl_permutationarray;
1511
1512 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1513 {
1514         //unsigned int hashdepth = 0;
1515         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1516         r_hlsl_permutation_t *p;
1517         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1518         {
1519                 if (p->mode == mode && p->permutation == permutation)
1520                 {
1521                         //if (hashdepth > 10)
1522                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1523                         return p;
1524                 }
1525                 //hashdepth++;
1526         }
1527         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1528         p->mode = mode;
1529         p->permutation = permutation;
1530         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1531         r_hlsl_permutationhash[mode][hashindex] = p;
1532         //if (hashdepth > 10)
1533         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1534         return p;
1535 }
1536
1537 #include <d3dx9.h>
1538 //#include <d3dx9shader.h>
1539 //#include <d3dx9mesh.h>
1540
1541 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1542 {
1543         DWORD *vsbin = NULL;
1544         DWORD *psbin = NULL;
1545         fs_offset_t vsbinsize;
1546         fs_offset_t psbinsize;
1547 //      IDirect3DVertexShader9 *vs = NULL;
1548 //      IDirect3DPixelShader9 *ps = NULL;
1549         ID3DXBuffer *vslog = NULL;
1550         ID3DXBuffer *vsbuffer = NULL;
1551         ID3DXConstantTable *vsconstanttable = NULL;
1552         ID3DXBuffer *pslog = NULL;
1553         ID3DXBuffer *psbuffer = NULL;
1554         ID3DXConstantTable *psconstanttable = NULL;
1555         int vsresult = 0;
1556         int psresult = 0;
1557         char temp[MAX_INPUTLINE];
1558         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1559         char vabuf[1024];
1560         qboolean debugshader = gl_paranoid.integer != 0;
1561         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1562         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1563         if (!debugshader)
1564         {
1565                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1566                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1567         }
1568         if ((!vsbin && vertstring) || (!psbin && fragstring))
1569         {
1570                 const char* dllnames_d3dx9 [] =
1571                 {
1572                         "d3dx9_43.dll",
1573                         "d3dx9_42.dll",
1574                         "d3dx9_41.dll",
1575                         "d3dx9_40.dll",
1576                         "d3dx9_39.dll",
1577                         "d3dx9_38.dll",
1578                         "d3dx9_37.dll",
1579                         "d3dx9_36.dll",
1580                         "d3dx9_35.dll",
1581                         "d3dx9_34.dll",
1582                         "d3dx9_33.dll",
1583                         "d3dx9_32.dll",
1584                         "d3dx9_31.dll",
1585                         "d3dx9_30.dll",
1586                         "d3dx9_29.dll",
1587                         "d3dx9_28.dll",
1588                         "d3dx9_27.dll",
1589                         "d3dx9_26.dll",
1590                         "d3dx9_25.dll",
1591                         "d3dx9_24.dll",
1592                         NULL
1593                 };
1594                 dllhandle_t d3dx9_dll = NULL;
1595                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1596                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1597                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1598                 dllfunction_t d3dx9_dllfuncs[] =
1599                 {
1600                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1601                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1602                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1603                         {NULL, NULL}
1604                 };
1605                 // 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...
1606 #ifndef ID3DXBuffer_GetBufferPointer
1607 #if !defined(__cplusplus) || defined(CINTERFACE)
1608 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1609 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1610 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1611 #else
1612 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1613 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1614 #define ID3DXBuffer_Release(p)            (p)->Release()
1615 #endif
1616 #endif
1617                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1618                 {
1619                         DWORD shaderflags = 0;
1620                         if (debugshader)
1621                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1622                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1623                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1624                         if (vertstring && vertstring[0])
1625                         {
1626                                 if (debugshader)
1627                                 {
1628                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1629                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1630                                 }
1631                                 else
1632                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1633                                 if (vsbuffer)
1634                                 {
1635                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1636                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1637                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1638                                         ID3DXBuffer_Release(vsbuffer);
1639                                 }
1640                                 if (vslog)
1641                                 {
1642                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1643                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1644                                         ID3DXBuffer_Release(vslog);
1645                                 }
1646                         }
1647                         if (fragstring && fragstring[0])
1648                         {
1649                                 if (debugshader)
1650                                 {
1651                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1652                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1653                                 }
1654                                 else
1655                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1656                                 if (psbuffer)
1657                                 {
1658                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1659                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1660                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1661                                         ID3DXBuffer_Release(psbuffer);
1662                                 }
1663                                 if (pslog)
1664                                 {
1665                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1666                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1667                                         ID3DXBuffer_Release(pslog);
1668                                 }
1669                         }
1670                         Sys_UnloadLibrary(&d3dx9_dll);
1671                 }
1672                 else
1673                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1674         }
1675         if (vsbin && psbin)
1676         {
1677                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1678                 if (FAILED(vsresult))
1679                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1680                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1681                 if (FAILED(psresult))
1682                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1683         }
1684         // free the shader data
1685         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1686         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1687 }
1688
1689 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1690 {
1691         int i;
1692         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1693         int vertstring_length = 0;
1694         int geomstring_length = 0;
1695         int fragstring_length = 0;
1696         char *t;
1697         char *sourcestring;
1698         char *vertstring, *geomstring, *fragstring;
1699         char permutationname[256];
1700         char cachename[256];
1701         int vertstrings_count = 0;
1702         int geomstrings_count = 0;
1703         int fragstrings_count = 0;
1704         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1705         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1706         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1707
1708         if (p->compiled)
1709                 return;
1710         p->compiled = true;
1711         p->vertexshader = NULL;
1712         p->pixelshader = NULL;
1713
1714         permutationname[0] = 0;
1715         cachename[0] = 0;
1716         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1717
1718         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1719         strlcat(cachename, "hlsl/", sizeof(cachename));
1720
1721         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1722         vertstrings_count = 0;
1723         geomstrings_count = 0;
1724         fragstrings_count = 0;
1725         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1726         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1727         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1728
1729         // the first pretext is which type of shader to compile as
1730         // (later these will all be bound together as a program object)
1731         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1732         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1733         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1734
1735         // the second pretext is the mode (for example a light source)
1736         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1737         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1738         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1739         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1740         strlcat(cachename, modeinfo->name, sizeof(cachename));
1741
1742         // now add all the permutation pretexts
1743         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1744         {
1745                 if (permutation & (1<<i))
1746                 {
1747                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1748                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1749                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1750                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1751                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1752                 }
1753                 else
1754                 {
1755                         // keep line numbers correct
1756                         vertstrings_list[vertstrings_count++] = "\n";
1757                         geomstrings_list[geomstrings_count++] = "\n";
1758                         fragstrings_list[fragstrings_count++] = "\n";
1759                 }
1760         }
1761
1762         // add static parms
1763         R_CompileShader_AddStaticParms(mode, permutation);
1764         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1765         vertstrings_count += shaderstaticparms_count;
1766         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1767         geomstrings_count += shaderstaticparms_count;
1768         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1769         fragstrings_count += shaderstaticparms_count;
1770
1771         // replace spaces in the cachename with _ characters
1772         for (i = 0;cachename[i];i++)
1773                 if (cachename[i] == ' ')
1774                         cachename[i] = '_';
1775
1776         // now append the shader text itself
1777         vertstrings_list[vertstrings_count++] = sourcestring;
1778         geomstrings_list[geomstrings_count++] = sourcestring;
1779         fragstrings_list[fragstrings_count++] = sourcestring;
1780
1781         vertstring_length = 0;
1782         for (i = 0;i < vertstrings_count;i++)
1783                 vertstring_length += (int)strlen(vertstrings_list[i]);
1784         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1785         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1786                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1787
1788         geomstring_length = 0;
1789         for (i = 0;i < geomstrings_count;i++)
1790                 geomstring_length += (int)strlen(geomstrings_list[i]);
1791         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1792         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1793                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1794
1795         fragstring_length = 0;
1796         for (i = 0;i < fragstrings_count;i++)
1797                 fragstring_length += (int)strlen(fragstrings_list[i]);
1798         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1799         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1800                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1801
1802         // try to load the cached shader, or generate one
1803         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1804
1805         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1806                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1807         else
1808                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1809
1810         // free the strings
1811         if (vertstring)
1812                 Mem_Free(vertstring);
1813         if (geomstring)
1814                 Mem_Free(geomstring);
1815         if (fragstring)
1816                 Mem_Free(fragstring);
1817         if (sourcestring)
1818                 Mem_Free(sourcestring);
1819 }
1820
1821 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1822 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1823 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);}
1824 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);}
1825 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);}
1826 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);}
1827
1828 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1829 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1830 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);}
1831 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);}
1832 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);}
1833 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);}
1834
1835 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1836 {
1837         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1838         if (r_hlsl_permutation != perm)
1839         {
1840                 r_hlsl_permutation = perm;
1841                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1842                 {
1843                         if (!r_hlsl_permutation->compiled)
1844                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1845                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1846                         {
1847                                 // remove features until we find a valid permutation
1848                                 int i;
1849                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1850                                 {
1851                                         // reduce i more quickly whenever it would not remove any bits
1852                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1853                                         if (!(permutation & j))
1854                                                 continue;
1855                                         permutation -= j;
1856                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1857                                         if (!r_hlsl_permutation->compiled)
1858                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1859                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1860                                                 break;
1861                                 }
1862                                 if (i >= SHADERPERMUTATION_COUNT)
1863                                 {
1864                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1865                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1866                                         return; // no bit left to clear, entire mode is broken
1867                                 }
1868                         }
1869                 }
1870                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1871                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1872         }
1873         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1874         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1875         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1876 }
1877 #endif
1878
1879 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1880 {
1881         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1882         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1883         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1884         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1885 }
1886
1887 void R_GLSL_Restart_f(void)
1888 {
1889         unsigned int i, limit;
1890         if (glslshaderstring)
1891                 Mem_Free(glslshaderstring);
1892         glslshaderstring = NULL;
1893         if (hlslshaderstring)
1894                 Mem_Free(hlslshaderstring);
1895         hlslshaderstring = NULL;
1896         switch(vid.renderpath)
1897         {
1898         case RENDERPATH_D3D9:
1899 #ifdef SUPPORTD3D
1900                 {
1901                         r_hlsl_permutation_t *p;
1902                         r_hlsl_permutation = NULL;
1903                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1904                         for (i = 0;i < limit;i++)
1905                         {
1906                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1907                                 {
1908                                         if (p->vertexshader)
1909                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1910                                         if (p->pixelshader)
1911                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1912                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1913                                 }
1914                         }
1915                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1916                 }
1917 #endif
1918                 break;
1919         case RENDERPATH_D3D10:
1920                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1921                 break;
1922         case RENDERPATH_D3D11:
1923                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1924                 break;
1925         case RENDERPATH_GL20:
1926         case RENDERPATH_GLES2:
1927                 {
1928                         r_glsl_permutation_t *p;
1929                         r_glsl_permutation = NULL;
1930                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1931                         for (i = 0;i < limit;i++)
1932                         {
1933                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1934                                 {
1935                                         GL_Backend_FreeProgram(p->program);
1936                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1937                                 }
1938                         }
1939                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1940                 }
1941                 break;
1942         case RENDERPATH_GL11:
1943         case RENDERPATH_GL13:
1944         case RENDERPATH_GLES1:
1945                 break;
1946         case RENDERPATH_SOFT:
1947                 break;
1948         }
1949 }
1950
1951 static void R_GLSL_DumpShader_f(void)
1952 {
1953         int i, language, mode, dupe;
1954         char *text;
1955         shadermodeinfo_t *modeinfo;
1956         qfile_t *file;
1957
1958         for (language = 0;language < 2;language++)
1959         {
1960                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1961                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1962                 {
1963                         // don't dump the same file multiple times (most or all shaders come from the same file)
1964                         for (dupe = mode - 1;dupe >= 0;dupe--)
1965                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1966                                         break;
1967                         if (dupe >= 0)
1968                                 continue;
1969                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1970                         if (!text)
1971                                 continue;
1972                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1973                         if (file)
1974                         {
1975                                 FS_Print(file, "/* The engine may define the following macros:\n");
1976                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1977                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1978                                         FS_Print(file, modeinfo[i].pretext);
1979                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1980                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1981                                 FS_Print(file, "*/\n");
1982                                 FS_Print(file, text);
1983                                 FS_Close(file);
1984                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1985                         }
1986                         else
1987                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1988                         Mem_Free(text);
1989                 }
1990         }
1991 }
1992
1993 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1994 {
1995         unsigned int permutation = 0;
1996         if (r_trippy.integer && !notrippy)
1997                 permutation |= SHADERPERMUTATION_TRIPPY;
1998         permutation |= SHADERPERMUTATION_VIEWTINT;
1999         if (first)
2000                 permutation |= SHADERPERMUTATION_DIFFUSE;
2001         if (second)
2002                 permutation |= SHADERPERMUTATION_SPECULAR;
2003         if (texturemode == GL_MODULATE)
2004                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2005         else if (texturemode == GL_ADD)
2006                 permutation |= SHADERPERMUTATION_GLOW;
2007         else if (texturemode == GL_DECAL)
2008                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2009         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2010                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2011         if (suppresstexalpha)
2012                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2013         if (!second)
2014                 texturemode = GL_MODULATE;
2015         if (vid.allowalphatocoverage)
2016                 GL_AlphaToCoverage(false);
2017         switch (vid.renderpath)
2018         {
2019         case RENDERPATH_D3D9:
2020 #ifdef SUPPORTD3D
2021                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2022                 R_Mesh_TexBind(GL20TU_FIRST , first );
2023                 R_Mesh_TexBind(GL20TU_SECOND, second);
2024                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2025                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2026 #endif
2027                 break;
2028         case RENDERPATH_D3D10:
2029                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2030                 break;
2031         case RENDERPATH_D3D11:
2032                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2033                 break;
2034         case RENDERPATH_GL20:
2035         case RENDERPATH_GLES2:
2036                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2037                 if (r_glsl_permutation->tex_Texture_First >= 0)
2038                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2039                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2040                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2041                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2042                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2043                 break;
2044         case RENDERPATH_GL13:
2045         case RENDERPATH_GLES1:
2046                 R_Mesh_TexBind(0, first );
2047                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2048                 R_Mesh_TexMatrix(0, NULL);
2049                 R_Mesh_TexBind(1, second);
2050                 if (second)
2051                 {
2052                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2053                         R_Mesh_TexMatrix(1, NULL);
2054                 }
2055                 break;
2056         case RENDERPATH_GL11:
2057                 R_Mesh_TexBind(0, first );
2058                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2059                 R_Mesh_TexMatrix(0, NULL);
2060                 break;
2061         case RENDERPATH_SOFT:
2062                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2063                 R_Mesh_TexBind(GL20TU_FIRST , first );
2064                 R_Mesh_TexBind(GL20TU_SECOND, second);
2065                 break;
2066         }
2067 }
2068
2069 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2070 {
2071         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2072 }
2073
2074 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2075 {
2076         unsigned int permutation = 0;
2077         if (r_trippy.integer && !notrippy)
2078                 permutation |= SHADERPERMUTATION_TRIPPY;
2079         if (depthrgb)
2080                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2081         if (skeletal)
2082                 permutation |= SHADERPERMUTATION_SKELETAL;
2083
2084         if (vid.allowalphatocoverage)
2085                 GL_AlphaToCoverage(false);
2086         switch (vid.renderpath)
2087         {
2088         case RENDERPATH_D3D9:
2089 #ifdef SUPPORTD3D
2090                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2091 #endif
2092                 break;
2093         case RENDERPATH_D3D10:
2094                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2095                 break;
2096         case RENDERPATH_D3D11:
2097                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2098                 break;
2099         case RENDERPATH_GL20:
2100         case RENDERPATH_GLES2:
2101                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2102 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2103                 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);
2104 #endif
2105                 break;
2106         case RENDERPATH_GL13:
2107         case RENDERPATH_GLES1:
2108                 R_Mesh_TexBind(0, 0);
2109                 R_Mesh_TexBind(1, 0);
2110                 break;
2111         case RENDERPATH_GL11:
2112                 R_Mesh_TexBind(0, 0);
2113                 break;
2114         case RENDERPATH_SOFT:
2115                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2116                 break;
2117         }
2118 }
2119
2120 extern qboolean r_shadow_usingdeferredprepass;
2121 extern rtexture_t *r_shadow_attenuationgradienttexture;
2122 extern rtexture_t *r_shadow_attenuation2dtexture;
2123 extern rtexture_t *r_shadow_attenuation3dtexture;
2124 extern qboolean r_shadow_usingshadowmap2d;
2125 extern qboolean r_shadow_usingshadowmaportho;
2126 extern float r_shadow_shadowmap_texturescale[2];
2127 extern float r_shadow_shadowmap_parameters[4];
2128 extern qboolean r_shadow_shadowmapvsdct;
2129 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2130 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2131 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2132 extern matrix4x4_t r_shadow_shadowmapmatrix;
2133 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2134 extern int r_shadow_prepass_width;
2135 extern int r_shadow_prepass_height;
2136 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2137 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2138 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2139 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2140
2141 #define BLENDFUNC_ALLOWS_COLORMOD      1
2142 #define BLENDFUNC_ALLOWS_FOG           2
2143 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2144 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2145 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2146 static int R_BlendFuncFlags(int src, int dst)
2147 {
2148         int r = 0;
2149
2150         // a blendfunc allows colormod if:
2151         // a) it can never keep the destination pixel invariant, or
2152         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2153         // this is to prevent unintended side effects from colormod
2154
2155         // a blendfunc allows fog if:
2156         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2157         // this is to prevent unintended side effects from fog
2158
2159         // these checks are the output of fogeval.pl
2160
2161         r |= BLENDFUNC_ALLOWS_COLORMOD;
2162         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2163         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2164         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2165         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2166         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2167         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2168         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2169         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2170         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2171         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2172         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2173         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2174         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2175         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2176         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2177         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2178         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2180         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2181         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2182         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2183
2184         return r;
2185 }
2186
2187 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)
2188 {
2189         // select a permutation of the lighting shader appropriate to this
2190         // combination of texture, entity, light source, and fogging, only use the
2191         // minimum features necessary to avoid wasting rendering time in the
2192         // fragment shader on features that are not being used
2193         unsigned int permutation = 0;
2194         unsigned int mode = 0;
2195         int blendfuncflags;
2196         static float dummy_colormod[3] = {1, 1, 1};
2197         float *colormod = rsurface.colormod;
2198         float m16f[16];
2199         matrix4x4_t tempmatrix;
2200         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2201         if (r_trippy.integer && !notrippy)
2202                 permutation |= SHADERPERMUTATION_TRIPPY;
2203         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2204                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2205         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2206                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2207         if (rsurfacepass == RSURFPASS_BACKGROUND)
2208         {
2209                 // distorted background
2210                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2211                 {
2212                         mode = SHADERMODE_WATER;
2213                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2214                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2215                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2216                         {
2217                                 // this is the right thing to do for wateralpha
2218                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2219                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2220                         }
2221                         else
2222                         {
2223                                 // this is the right thing to do for entity alpha
2224                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2225                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2226                         }
2227                 }
2228                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2229                 {
2230                         mode = SHADERMODE_REFRACTION;
2231                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2232                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2233                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2234                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2235                 }
2236                 else
2237                 {
2238                         mode = SHADERMODE_GENERIC;
2239                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2240                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2241                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2242                 }
2243                 if (vid.allowalphatocoverage)
2244                         GL_AlphaToCoverage(false);
2245         }
2246         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2247         {
2248                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2249                 {
2250                         switch(rsurface.texture->offsetmapping)
2251                         {
2252                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2253                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2254                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2255                         case OFFSETMAPPING_OFF: break;
2256                         }
2257                 }
2258                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2259                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2260                 // normalmap (deferred prepass), may use alpha test on diffuse
2261                 mode = SHADERMODE_DEFERREDGEOMETRY;
2262                 GL_BlendFunc(GL_ONE, GL_ZERO);
2263                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2264                 if (vid.allowalphatocoverage)
2265                         GL_AlphaToCoverage(false);
2266         }
2267         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2268         {
2269                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2270                 {
2271                         switch(rsurface.texture->offsetmapping)
2272                         {
2273                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2274                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2275                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2276                         case OFFSETMAPPING_OFF: break;
2277                         }
2278                 }
2279                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2280                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2281                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2282                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2283                 // light source
2284                 mode = SHADERMODE_LIGHTSOURCE;
2285                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2286                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2287                 if (diffusescale > 0)
2288                         permutation |= SHADERPERMUTATION_DIFFUSE;
2289                 if (specularscale > 0)
2290                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2291                 if (r_refdef.fogenabled)
2292                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2293                 if (rsurface.texture->colormapping)
2294                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2295                 if (r_shadow_usingshadowmap2d)
2296                 {
2297                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2298                         if(r_shadow_shadowmapvsdct)
2299                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2300
2301                         if (r_shadow_shadowmap2ddepthbuffer)
2302                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2303                 }
2304                 if (rsurface.texture->reflectmasktexture)
2305                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2306                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2307                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2308                 if (vid.allowalphatocoverage)
2309                         GL_AlphaToCoverage(false);
2310         }
2311         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2312         {
2313                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2314                 {
2315                         switch(rsurface.texture->offsetmapping)
2316                         {
2317                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2318                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2319                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2320                         case OFFSETMAPPING_OFF: break;
2321                         }
2322                 }
2323                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2324                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2325                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2326                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2327                 // unshaded geometry (fullbright or ambient model lighting)
2328                 mode = SHADERMODE_FLATCOLOR;
2329                 ambientscale = diffusescale = specularscale = 0;
2330                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2331                         permutation |= SHADERPERMUTATION_GLOW;
2332                 if (r_refdef.fogenabled)
2333                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2334                 if (rsurface.texture->colormapping)
2335                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2336                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2337                 {
2338                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2339                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2340
2341                         if (r_shadow_shadowmap2ddepthbuffer)
2342                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2343                 }
2344                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2345                         permutation |= SHADERPERMUTATION_REFLECTION;
2346                 if (rsurface.texture->reflectmasktexture)
2347                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2348                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2349                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2350                 // when using alphatocoverage, we don't need alphakill
2351                 if (vid.allowalphatocoverage)
2352                 {
2353                         if (r_transparent_alphatocoverage.integer)
2354                         {
2355                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2356                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2357                         }
2358                         else
2359                                 GL_AlphaToCoverage(false);
2360                 }
2361         }
2362         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2363         {
2364                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2365                 {
2366                         switch(rsurface.texture->offsetmapping)
2367                         {
2368                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2369                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2370                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2371                         case OFFSETMAPPING_OFF: break;
2372                         }
2373                 }
2374                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2375                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2376                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2377                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2378                 // directional model lighting
2379                 mode = SHADERMODE_LIGHTDIRECTION;
2380                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2381                         permutation |= SHADERPERMUTATION_GLOW;
2382                 permutation |= SHADERPERMUTATION_DIFFUSE;
2383                 if (specularscale > 0)
2384                         permutation |= SHADERPERMUTATION_SPECULAR;
2385                 if (r_refdef.fogenabled)
2386                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2387                 if (rsurface.texture->colormapping)
2388                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2389                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2390                 {
2391                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2392                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2393
2394                         if (r_shadow_shadowmap2ddepthbuffer)
2395                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2396                 }
2397                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2398                         permutation |= SHADERPERMUTATION_REFLECTION;
2399                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2400                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2401                 if (rsurface.texture->reflectmasktexture)
2402                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2403                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2404                 {
2405                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2406                         if (r_shadow_bouncegriddirectional)
2407                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2408                 }
2409                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2410                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2411                 // when using alphatocoverage, we don't need alphakill
2412                 if (vid.allowalphatocoverage)
2413                 {
2414                         if (r_transparent_alphatocoverage.integer)
2415                         {
2416                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2417                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2418                         }
2419                         else
2420                                 GL_AlphaToCoverage(false);
2421                 }
2422         }
2423         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2424         {
2425                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2426                 {
2427                         switch(rsurface.texture->offsetmapping)
2428                         {
2429                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2430                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2431                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2432                         case OFFSETMAPPING_OFF: break;
2433                         }
2434                 }
2435                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2436                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2437                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2438                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2439                 // ambient model lighting
2440                 mode = SHADERMODE_LIGHTDIRECTION;
2441                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2442                         permutation |= SHADERPERMUTATION_GLOW;
2443                 if (r_refdef.fogenabled)
2444                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2445                 if (rsurface.texture->colormapping)
2446                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2447                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2448                 {
2449                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2450                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2451
2452                         if (r_shadow_shadowmap2ddepthbuffer)
2453                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2454                 }
2455                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2456                         permutation |= SHADERPERMUTATION_REFLECTION;
2457                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2458                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2459                 if (rsurface.texture->reflectmasktexture)
2460                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2461                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2462                 {
2463                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2464                         if (r_shadow_bouncegriddirectional)
2465                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2466                 }
2467                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2468                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2469                 // when using alphatocoverage, we don't need alphakill
2470                 if (vid.allowalphatocoverage)
2471                 {
2472                         if (r_transparent_alphatocoverage.integer)
2473                         {
2474                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2475                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2476                         }
2477                         else
2478                                 GL_AlphaToCoverage(false);
2479                 }
2480         }
2481         else
2482         {
2483                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2484                 {
2485                         switch(rsurface.texture->offsetmapping)
2486                         {
2487                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2488                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2489                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2490                         case OFFSETMAPPING_OFF: break;
2491                         }
2492                 }
2493                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2494                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2495                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2496                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2497                 // lightmapped wall
2498                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2499                         permutation |= SHADERPERMUTATION_GLOW;
2500                 if (r_refdef.fogenabled)
2501                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2502                 if (rsurface.texture->colormapping)
2503                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2504                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2505                 {
2506                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2507                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2508
2509                         if (r_shadow_shadowmap2ddepthbuffer)
2510                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2511                 }
2512                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2513                         permutation |= SHADERPERMUTATION_REFLECTION;
2514                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2515                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2516                 if (rsurface.texture->reflectmasktexture)
2517                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2518                 if (FAKELIGHT_ENABLED)
2519                 {
2520                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2521                         mode = SHADERMODE_FAKELIGHT;
2522                         permutation |= SHADERPERMUTATION_DIFFUSE;
2523                         if (specularscale > 0)
2524                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2525                 }
2526                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2527                 {
2528                         // deluxemapping (light direction texture)
2529                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2530                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2531                         else
2532                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2533                         permutation |= SHADERPERMUTATION_DIFFUSE;
2534                         if (specularscale > 0)
2535                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2536                 }
2537                 else if (r_glsl_deluxemapping.integer >= 2)
2538                 {
2539                         // fake deluxemapping (uniform light direction in tangentspace)
2540                         if (rsurface.uselightmaptexture)
2541                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2542                         else
2543                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2544                         permutation |= SHADERPERMUTATION_DIFFUSE;
2545                         if (specularscale > 0)
2546                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2547                 }
2548                 else if (rsurface.uselightmaptexture)
2549                 {
2550                         // ordinary lightmapping (q1bsp, q3bsp)
2551                         mode = SHADERMODE_LIGHTMAP;
2552                 }
2553                 else
2554                 {
2555                         // ordinary vertex coloring (q3bsp)
2556                         mode = SHADERMODE_VERTEXCOLOR;
2557                 }
2558                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2559                 {
2560                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2561                         if (r_shadow_bouncegriddirectional)
2562                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2563                 }
2564                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2565                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2566                 // when using alphatocoverage, we don't need alphakill
2567                 if (vid.allowalphatocoverage)
2568                 {
2569                         if (r_transparent_alphatocoverage.integer)
2570                         {
2571                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2572                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2573                         }
2574                         else
2575                                 GL_AlphaToCoverage(false);
2576                 }
2577         }
2578         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2579                 colormod = dummy_colormod;
2580         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2581                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2582         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2583                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2584         switch(vid.renderpath)
2585         {
2586         case RENDERPATH_D3D9:
2587 #ifdef SUPPORTD3D
2588                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2589                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2590                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2591                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2592                 if (mode == SHADERMODE_LIGHTSOURCE)
2593                 {
2594                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2595                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2596                 }
2597                 else
2598                 {
2599                         if (mode == SHADERMODE_LIGHTDIRECTION)
2600                         {
2601                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2602                         }
2603                 }
2604                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2605                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2606                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2607                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2608                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2609
2610                 if (mode == SHADERMODE_LIGHTSOURCE)
2611                 {
2612                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2613                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2614                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2615                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2616                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2617
2618                         // additive passes are only darkened by fog, not tinted
2619                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2620                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2621                 }
2622                 else
2623                 {
2624                         if (mode == SHADERMODE_FLATCOLOR)
2625                         {
2626                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2627                         }
2628                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2629                         {
2630                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2631                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2632                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2633                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2634                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2635                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2636                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2637                         }
2638                         else
2639                         {
2640                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2641                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2642                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2643                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2644                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2645                         }
2646                         // additive passes are only darkened by fog, not tinted
2647                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2648                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2649                         else
2650                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2651                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2652                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2653                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2654                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2655                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2656                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2657                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2658                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2659                         if (mode == SHADERMODE_WATER)
2660                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2661                 }
2662                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2663                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2664                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2665                 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));
2666                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2667                 if (rsurface.texture->pantstexture)
2668                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2669                 else
2670                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2671                 if (rsurface.texture->shirttexture)
2672                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2673                 else
2674                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2675                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2676                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2677                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2678                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2679                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2680                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2681                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2682                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2683                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2684                         );
2685                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2686                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2687                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2688                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2689
2690                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2691                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2692                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2693                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2694                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2695                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2696                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2697                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2698                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2699                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2700                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2701                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2702                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2703                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2704                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2705                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2706                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2707                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2708                 {
2709                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2710                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2711                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2712                 }
2713                 else
2714                 {
2715                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2716                 }
2717 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2718                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2719                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2720                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2721                 {
2722                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2723                         if (rsurface.rtlight)
2724                         {
2725                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2726                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2727                         }
2728                 }
2729 #endif
2730                 break;
2731         case RENDERPATH_D3D10:
2732                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2733                 break;
2734         case RENDERPATH_D3D11:
2735                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2736                 break;
2737         case RENDERPATH_GL20:
2738         case RENDERPATH_GLES2:
2739                 if (!vid.useinterleavedarrays)
2740                 {
2741                         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);
2742                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2743                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2744                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2745                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2746                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2747                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2748                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2749                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2750                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2751                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2752                 }
2753                 else
2754                 {
2755                         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);
2756                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2757                 }
2758                 // this has to be after RSurf_PrepareVerticesForBatch
2759                 if (rsurface.batchskeletaltransform3x4buffer)
2760                         permutation |= SHADERPERMUTATION_SKELETAL;
2761                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2762 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2763                 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);
2764 #endif
2765                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2766                 if (mode == SHADERMODE_LIGHTSOURCE)
2767                 {
2768                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2769                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2770                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2771                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2772                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2773                         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);
2774         
2775                         // additive passes are only darkened by fog, not tinted
2776                         if (r_glsl_permutation->loc_FogColor >= 0)
2777                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2778                         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);
2779                 }
2780                 else
2781                 {
2782                         if (mode == SHADERMODE_FLATCOLOR)
2783                         {
2784                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2785                         }
2786                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2787                         {
2788                                 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]);
2789                                 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]);
2790                                 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);
2791                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2792                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2793                                 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]);
2794                                 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]);
2795                         }
2796                         else
2797                         {
2798                                 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]);
2799                                 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]);
2800                                 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);
2801                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2802                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2803                         }
2804                         // additive passes are only darkened by fog, not tinted
2805                         if (r_glsl_permutation->loc_FogColor >= 0)
2806                         {
2807                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2808                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2809                                 else
2810                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2811                         }
2812                         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);
2813                         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]);
2814                         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]);
2815                         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]);
2816                         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]);
2817                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2818                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2819                         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);
2820                         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]);
2821                 }
2822                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2823                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2824                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2825                 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]);
2826                 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]);
2827
2828                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2829                 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));
2830                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2831                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2832                 {
2833                         if (rsurface.texture->pantstexture)
2834                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2835                         else
2836                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2837                 }
2838                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2839                 {
2840                         if (rsurface.texture->shirttexture)
2841                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2842                         else
2843                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2844                 }
2845                 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]);
2846                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2847                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2848                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2849                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2850                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2851                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2852                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2853                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2854                         );
2855                 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);
2856                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2857                 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]);
2858                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2859                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2860                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2861
2862                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2863                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2864                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2865                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2866                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2867                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2868                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2869                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2870                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2871                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2872                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2873                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2874                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2875                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2876                 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);
2877                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2878                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2879                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2880                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2881                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2882                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2883                 {
2884                         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);
2885                         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);
2886                         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);
2887                 }
2888                 else
2889                 {
2890                         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);
2891                 }
2892                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2893                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2894                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2895                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2896                 {
2897                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2898                         if (rsurface.rtlight)
2899                         {
2900                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2901                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2902                         }
2903                 }
2904                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2905                 CHECKGLERROR
2906                 break;
2907         case RENDERPATH_GL11:
2908         case RENDERPATH_GL13:
2909         case RENDERPATH_GLES1:
2910                 break;
2911         case RENDERPATH_SOFT:
2912                 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);
2913                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2914                 R_SetupShader_SetPermutationSoft(mode, permutation);
2915                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2916                 if (mode == SHADERMODE_LIGHTSOURCE)
2917                 {
2918                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2919                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2920                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2921                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2922                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2923                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2924         
2925                         // additive passes are only darkened by fog, not tinted
2926                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2927                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2928                 }
2929                 else
2930                 {
2931                         if (mode == SHADERMODE_FLATCOLOR)
2932                         {
2933                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2934                         }
2935                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2936                         {
2937                                 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]);
2938                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2939                                 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);
2940                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2941                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2942                                 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]);
2943                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2944                         }
2945                         else
2946                         {
2947                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2948                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2949                                 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);
2950                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2951                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2952                         }
2953                         // additive passes are only darkened by fog, not tinted
2954                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2955                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2956                         else
2957                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2958                         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);
2959                         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]);
2960                         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]);
2961                         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]);
2962                         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]);
2963                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2964                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2965                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2966                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2967                 }
2968                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2969                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2970                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2971                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2972                 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]);
2973
2974                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2975                 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));
2976                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2977                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2978                 {
2979                         if (rsurface.texture->pantstexture)
2980                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2981                         else
2982                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2983                 }
2984                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2985                 {
2986                         if (rsurface.texture->shirttexture)
2987                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2988                         else
2989                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2990                 }
2991                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2992                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2993                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2994                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2995                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2996                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2997                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2998                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2999                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3000                         );
3001                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3002                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3003                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3004                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3005
3006                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3007                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3008                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3009                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3010                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3011                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3012                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3013                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3014                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3015                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3016                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3017                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3018                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3019                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3020                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3021                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3022                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3023                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3024                 {
3025                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3026                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3027                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3028                 }
3029                 else
3030                 {
3031                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3032                 }
3033 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3034                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3035                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3036                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3037                 {
3038                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3039                         if (rsurface.rtlight)
3040                         {
3041                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3042                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3043                         }
3044                 }
3045                 break;
3046         }
3047 }
3048
3049 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3050 {
3051         // select a permutation of the lighting shader appropriate to this
3052         // combination of texture, entity, light source, and fogging, only use the
3053         // minimum features necessary to avoid wasting rendering time in the
3054         // fragment shader on features that are not being used
3055         unsigned int permutation = 0;
3056         unsigned int mode = 0;
3057         const float *lightcolorbase = rtlight->currentcolor;
3058         float ambientscale = rtlight->ambientscale;
3059         float diffusescale = rtlight->diffusescale;
3060         float specularscale = rtlight->specularscale;
3061         // this is the location of the light in view space
3062         vec3_t viewlightorigin;
3063         // this transforms from view space (camera) to light space (cubemap)
3064         matrix4x4_t viewtolight;
3065         matrix4x4_t lighttoview;
3066         float viewtolight16f[16];
3067         // light source
3068         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3069         if (rtlight->currentcubemap != r_texture_whitecube)
3070                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3071         if (diffusescale > 0)
3072                 permutation |= SHADERPERMUTATION_DIFFUSE;
3073         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3074                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3075         if (r_shadow_usingshadowmap2d)
3076         {
3077                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3078                 if (r_shadow_shadowmapvsdct)
3079                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3080
3081                 if (r_shadow_shadowmap2ddepthbuffer)
3082                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3083         }
3084         if (vid.allowalphatocoverage)
3085                 GL_AlphaToCoverage(false);
3086         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3087         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3088         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3089         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3090         switch(vid.renderpath)
3091         {
3092         case RENDERPATH_D3D9:
3093 #ifdef SUPPORTD3D
3094                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3095                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3096                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3097                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3098                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3099                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3100                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3101                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3102                 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);
3103                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3104                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3105
3106                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3107                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3108                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3109                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3110                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3111 #endif
3112                 break;
3113         case RENDERPATH_D3D10:
3114                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3115                 break;
3116         case RENDERPATH_D3D11:
3117                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3118                 break;
3119         case RENDERPATH_GL20:
3120         case RENDERPATH_GLES2:
3121                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3122                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3123                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3124                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3125                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3126                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3127                 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]);
3128                 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]);
3129                 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);
3130                 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]);
3131                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3132
3133                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3134                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3135                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3136                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3137                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3138                 break;
3139         case RENDERPATH_GL11:
3140         case RENDERPATH_GL13:
3141         case RENDERPATH_GLES1:
3142                 break;
3143         case RENDERPATH_SOFT:
3144                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3145                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3146                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3147                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3148                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3149                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3150                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3151                 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]);
3152                 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);
3153                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3154                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3155
3156                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3157                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3158                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3159                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3160                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3161                 break;
3162         }
3163 }
3164
3165 #define SKINFRAME_HASH 1024
3166
3167 typedef struct
3168 {
3169         int loadsequence; // incremented each level change
3170         memexpandablearray_t array;
3171         skinframe_t *hash[SKINFRAME_HASH];
3172 }
3173 r_skinframe_t;
3174 r_skinframe_t r_skinframe;
3175
3176 void R_SkinFrame_PrepareForPurge(void)
3177 {
3178         r_skinframe.loadsequence++;
3179         // wrap it without hitting zero
3180         if (r_skinframe.loadsequence >= 200)
3181                 r_skinframe.loadsequence = 1;
3182 }
3183
3184 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3185 {
3186         if (!skinframe)
3187                 return;
3188         // mark the skinframe as used for the purging code
3189         skinframe->loadsequence = r_skinframe.loadsequence;
3190 }
3191
3192 void R_SkinFrame_Purge(void)
3193 {
3194         int i;
3195         skinframe_t *s;
3196         for (i = 0;i < SKINFRAME_HASH;i++)
3197         {
3198                 for (s = r_skinframe.hash[i];s;s = s->next)
3199                 {
3200                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3201                         {
3202                                 if (s->merged == s->base)
3203                                         s->merged = NULL;
3204                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3205                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3206                                 R_PurgeTexture(s->merged);s->merged = NULL;
3207                                 R_PurgeTexture(s->base  );s->base   = NULL;
3208                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3209                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3210                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3211                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3212                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3213                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3214                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3215                                 s->loadsequence = 0;
3216                         }
3217                 }
3218         }
3219 }
3220
3221 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3222         skinframe_t *item;
3223         char basename[MAX_QPATH];
3224
3225         Image_StripImageExtension(name, basename, sizeof(basename));
3226
3227         if( last == NULL ) {
3228                 int hashindex;
3229                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3230                 item = r_skinframe.hash[hashindex];
3231         } else {
3232                 item = last->next;
3233         }
3234
3235         // linearly search through the hash bucket
3236         for( ; item ; item = item->next ) {
3237                 if( !strcmp( item->basename, basename ) ) {
3238                         return item;
3239                 }
3240         }
3241         return NULL;
3242 }
3243
3244 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3245 {
3246         skinframe_t *item;
3247         int hashindex;
3248         char basename[MAX_QPATH];
3249
3250         Image_StripImageExtension(name, basename, sizeof(basename));
3251
3252         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3253         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3254                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3255                         break;
3256
3257         if (!item) {
3258                 rtexture_t *dyntexture;
3259                 // check whether its a dynamic texture
3260                 dyntexture = CL_GetDynTexture( basename );
3261                 if (!add && !dyntexture)
3262                         return NULL;
3263                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3264                 memset(item, 0, sizeof(*item));
3265                 strlcpy(item->basename, basename, sizeof(item->basename));
3266                 item->base = dyntexture; // either NULL or dyntexture handle
3267                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3268                 item->comparewidth = comparewidth;
3269                 item->compareheight = compareheight;
3270                 item->comparecrc = comparecrc;
3271                 item->next = r_skinframe.hash[hashindex];
3272                 r_skinframe.hash[hashindex] = item;
3273         }
3274         else if (textureflags & TEXF_FORCE_RELOAD)
3275         {
3276                 rtexture_t *dyntexture;
3277                 // check whether its a dynamic texture
3278                 dyntexture = CL_GetDynTexture( basename );
3279                 if (!add && !dyntexture)
3280                         return NULL;
3281                 if (item->merged == item->base)
3282                         item->merged = NULL;
3283                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3284                 R_PurgeTexture(item->stain );item->stain  = NULL;
3285                 R_PurgeTexture(item->merged);item->merged = NULL;
3286                 R_PurgeTexture(item->base  );item->base   = NULL;
3287                 R_PurgeTexture(item->pants );item->pants  = NULL;
3288                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3289                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3290                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3291                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3292                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3293         R_PurgeTexture(item->reflect);item->reflect = NULL;
3294                 item->loadsequence = 0;
3295         }
3296         else if( item->base == NULL )
3297         {
3298                 rtexture_t *dyntexture;
3299                 // check whether its a dynamic texture
3300                 // 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]
3301                 dyntexture = CL_GetDynTexture( basename );
3302                 item->base = dyntexture; // either NULL or dyntexture handle
3303         }
3304
3305         R_SkinFrame_MarkUsed(item);
3306         return item;
3307 }
3308
3309 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3310         { \
3311                 unsigned long long avgcolor[5], wsum; \
3312                 int pix, comp, w; \
3313                 avgcolor[0] = 0; \
3314                 avgcolor[1] = 0; \
3315                 avgcolor[2] = 0; \
3316                 avgcolor[3] = 0; \
3317                 avgcolor[4] = 0; \
3318                 wsum = 0; \
3319                 for(pix = 0; pix < cnt; ++pix) \
3320                 { \
3321                         w = 0; \
3322                         for(comp = 0; comp < 3; ++comp) \
3323                                 w += getpixel; \
3324                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3325                         { \
3326                                 ++wsum; \
3327                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3328                                 w = getpixel; \
3329                                 for(comp = 0; comp < 3; ++comp) \
3330                                         avgcolor[comp] += getpixel * w; \
3331                                 avgcolor[3] += w; \
3332                         } \
3333                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3334                         avgcolor[4] += getpixel; \
3335                 } \
3336                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3337                         avgcolor[3] = 1; \
3338                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3339                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3340                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3341                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3342         }
3343
3344 extern cvar_t gl_picmip;
3345 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3346 {
3347         int j;
3348         unsigned char *pixels;
3349         unsigned char *bumppixels;
3350         unsigned char *basepixels = NULL;
3351         int basepixels_width = 0;
3352         int basepixels_height = 0;
3353         skinframe_t *skinframe;
3354         rtexture_t *ddsbase = NULL;
3355         qboolean ddshasalpha = false;
3356         float ddsavgcolor[4];
3357         char basename[MAX_QPATH];
3358         int miplevel = R_PicmipForFlags(textureflags);
3359         int savemiplevel = miplevel;
3360         int mymiplevel;
3361         char vabuf[1024];
3362
3363         if (cls.state == ca_dedicated)
3364                 return NULL;
3365
3366         // return an existing skinframe if already loaded
3367         // if loading of the first image fails, don't make a new skinframe as it
3368         // would cause all future lookups of this to be missing
3369         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3370         if (skinframe && skinframe->base)
3371                 return skinframe;
3372
3373         Image_StripImageExtension(name, basename, sizeof(basename));
3374
3375         // check for DDS texture file first
3376         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3377         {
3378                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3379                 if (basepixels == NULL)
3380                         return NULL;
3381         }
3382
3383         // FIXME handle miplevel
3384
3385         if (developer_loading.integer)
3386                 Con_Printf("loading skin \"%s\"\n", name);
3387
3388         // we've got some pixels to store, so really allocate this new texture now
3389         if (!skinframe)
3390                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3391         textureflags &= ~TEXF_FORCE_RELOAD;
3392         skinframe->stain = NULL;
3393         skinframe->merged = NULL;
3394         skinframe->base = NULL;
3395         skinframe->pants = NULL;
3396         skinframe->shirt = NULL;
3397         skinframe->nmap = NULL;
3398         skinframe->gloss = NULL;
3399         skinframe->glow = NULL;
3400         skinframe->fog = NULL;
3401         skinframe->reflect = NULL;
3402         skinframe->hasalpha = false;
3403         // we could store the q2animname here too
3404
3405         if (ddsbase)
3406         {
3407                 skinframe->base = ddsbase;
3408                 skinframe->hasalpha = ddshasalpha;
3409                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3410                 if (r_loadfog && skinframe->hasalpha)
3411                         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);
3412                 //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]);
3413         }
3414         else
3415         {
3416                 basepixels_width = image_width;
3417                 basepixels_height = image_height;
3418                 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);
3419                 if (textureflags & TEXF_ALPHA)
3420                 {
3421                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3422                         {
3423                                 if (basepixels[j] < 255)
3424                                 {
3425                                         skinframe->hasalpha = true;
3426                                         break;
3427                                 }
3428                         }
3429                         if (r_loadfog && skinframe->hasalpha)
3430                         {
3431                                 // has transparent pixels
3432                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3433                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3434                                 {
3435                                         pixels[j+0] = 255;
3436                                         pixels[j+1] = 255;
3437                                         pixels[j+2] = 255;
3438                                         pixels[j+3] = basepixels[j+3];
3439                                 }
3440                                 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);
3441                                 Mem_Free(pixels);
3442                         }
3443                 }
3444                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3445 #ifndef USE_GLES2
3446                 //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]);
3447                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3448                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3449                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3450                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3451 #endif
3452         }
3453
3454         if (r_loaddds)
3455         {
3456                 mymiplevel = savemiplevel;
3457                 if (r_loadnormalmap)
3458                         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);
3459                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3460                 if (r_loadgloss)
3461                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3462                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3463                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3464                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3465         }
3466
3467         // _norm is the name used by tenebrae and has been adopted as standard
3468         if (r_loadnormalmap && skinframe->nmap == NULL)
3469         {
3470                 mymiplevel = savemiplevel;
3471                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3472                 {
3473                         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);
3474                         Mem_Free(pixels);
3475                         pixels = NULL;
3476                 }
3477                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3478                 {
3479                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3480                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3481                         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);
3482                         Mem_Free(pixels);
3483                         Mem_Free(bumppixels);
3484                 }
3485                 else if (r_shadow_bumpscale_basetexture.value > 0)
3486                 {
3487                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3488                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3489                         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);
3490                         Mem_Free(pixels);
3491                 }
3492 #ifndef USE_GLES2
3493                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3494                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3495 #endif
3496         }
3497
3498         // _luma is supported only for tenebrae compatibility
3499         // _glow is the preferred name
3500         mymiplevel = savemiplevel;
3501         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))))
3502         {
3503                 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);
3504 #ifndef USE_GLES2
3505                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3506                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3507 #endif
3508                 Mem_Free(pixels);pixels = NULL;
3509         }
3510
3511         mymiplevel = savemiplevel;
3512         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3513         {
3514                 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);
3515 #ifndef USE_GLES2
3516                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3517                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3518 #endif
3519                 Mem_Free(pixels);
3520                 pixels = NULL;
3521         }
3522
3523         mymiplevel = savemiplevel;
3524         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3525         {
3526                 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);
3527 #ifndef USE_GLES2
3528                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3529                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3530 #endif
3531                 Mem_Free(pixels);
3532                 pixels = NULL;
3533         }
3534
3535         mymiplevel = savemiplevel;
3536         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3537         {
3538                 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);
3539 #ifndef USE_GLES2
3540                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3541                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3542 #endif
3543                 Mem_Free(pixels);
3544                 pixels = NULL;
3545         }
3546
3547         mymiplevel = savemiplevel;
3548         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3549         {
3550                 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);
3551 #ifndef USE_GLES2
3552                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3553                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3554 #endif
3555                 Mem_Free(pixels);
3556                 pixels = NULL;
3557         }
3558
3559         if (basepixels)
3560                 Mem_Free(basepixels);
3561
3562         return skinframe;
3563 }
3564
3565 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3566 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3567 {
3568         int i;
3569         unsigned char *temp1, *temp2;
3570         skinframe_t *skinframe;
3571         char vabuf[1024];
3572
3573         if (cls.state == ca_dedicated)
3574                 return NULL;
3575
3576         // if already loaded just return it, otherwise make a new skinframe
3577         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3578         if (skinframe->base)
3579                 return skinframe;
3580         textureflags &= ~TEXF_FORCE_RELOAD;
3581
3582         skinframe->stain = NULL;
3583         skinframe->merged = NULL;
3584         skinframe->base = NULL;
3585         skinframe->pants = NULL;
3586         skinframe->shirt = NULL;
3587         skinframe->nmap = NULL;
3588         skinframe->gloss = NULL;
3589         skinframe->glow = NULL;
3590         skinframe->fog = NULL;
3591         skinframe->reflect = NULL;
3592         skinframe->hasalpha = false;
3593
3594         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3595         if (!skindata)
3596                 return NULL;
3597
3598         if (developer_loading.integer)
3599                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3600
3601         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3602         {
3603                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3604                 temp2 = temp1 + width * height * 4;
3605                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3606                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3607                 Mem_Free(temp1);
3608         }
3609         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3610         if (textureflags & TEXF_ALPHA)
3611         {
3612                 for (i = 3;i < width * height * 4;i += 4)
3613                 {
3614                         if (skindata[i] < 255)
3615                         {
3616                                 skinframe->hasalpha = true;
3617                                 break;
3618                         }
3619                 }
3620                 if (r_loadfog && skinframe->hasalpha)
3621                 {
3622                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3623                         memcpy(fogpixels, skindata, width * height * 4);
3624                         for (i = 0;i < width * height * 4;i += 4)
3625                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3626                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3627                         Mem_Free(fogpixels);
3628                 }
3629         }
3630
3631         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3632         //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]);
3633
3634         return skinframe;
3635 }
3636
3637 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3638 {
3639         int i;
3640         int featuresmask;
3641         skinframe_t *skinframe;
3642
3643         if (cls.state == ca_dedicated)
3644                 return NULL;
3645
3646         // if already loaded just return it, otherwise make a new skinframe
3647         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3648         if (skinframe->base)
3649                 return skinframe;
3650         //textureflags &= ~TEXF_FORCE_RELOAD;
3651
3652         skinframe->stain = NULL;
3653         skinframe->merged = NULL;
3654         skinframe->base = NULL;
3655         skinframe->pants = NULL;
3656         skinframe->shirt = NULL;
3657         skinframe->nmap = NULL;
3658         skinframe->gloss = NULL;
3659         skinframe->glow = NULL;
3660         skinframe->fog = NULL;
3661         skinframe->reflect = NULL;
3662         skinframe->hasalpha = false;
3663
3664         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3665         if (!skindata)
3666                 return NULL;
3667
3668         if (developer_loading.integer)
3669                 Con_Printf("loading quake skin \"%s\"\n", name);
3670
3671         // 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)
3672         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3673         memcpy(skinframe->qpixels, skindata, width*height);
3674         skinframe->qwidth = width;
3675         skinframe->qheight = height;
3676
3677         featuresmask = 0;
3678         for (i = 0;i < width * height;i++)
3679                 featuresmask |= palette_featureflags[skindata[i]];
3680
3681         skinframe->hasalpha = false;
3682         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3683         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3684         skinframe->qgeneratemerged = true;
3685         skinframe->qgeneratebase = skinframe->qhascolormapping;
3686         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3687
3688         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3689         //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]);
3690
3691         return skinframe;
3692 }
3693
3694 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3695 {
3696         int width;
3697         int height;
3698         unsigned char *skindata;
3699         char vabuf[1024];
3700
3701         if (!skinframe->qpixels)
3702                 return;
3703
3704         if (!skinframe->qhascolormapping)
3705                 colormapped = false;
3706
3707         if (colormapped)
3708         {
3709                 if (!skinframe->qgeneratebase)
3710                         return;
3711         }
3712         else
3713         {
3714                 if (!skinframe->qgeneratemerged)
3715                         return;
3716         }
3717
3718         width = skinframe->qwidth;
3719         height = skinframe->qheight;
3720         skindata = skinframe->qpixels;
3721
3722         if (skinframe->qgeneratenmap)
3723         {
3724                 unsigned char *temp1, *temp2;
3725                 skinframe->qgeneratenmap = false;
3726                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3727                 temp2 = temp1 + width * height * 4;
3728                 // use either a custom palette or the quake palette
3729                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3730                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3731                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3732                 Mem_Free(temp1);
3733         }
3734
3735         if (skinframe->qgenerateglow)
3736         {
3737                 skinframe->qgenerateglow = false;
3738                 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
3739         }
3740
3741         if (colormapped)
3742         {
3743                 skinframe->qgeneratebase = false;
3744                 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);
3745                 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);
3746                 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);
3747         }
3748         else
3749         {
3750                 skinframe->qgeneratemerged = false;
3751                 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);
3752         }
3753
3754         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3755         {
3756                 Mem_Free(skinframe->qpixels);
3757                 skinframe->qpixels = NULL;
3758         }
3759 }
3760
3761 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)
3762 {
3763         int i;
3764         skinframe_t *skinframe;
3765         char vabuf[1024];
3766
3767         if (cls.state == ca_dedicated)
3768                 return NULL;
3769
3770         // if already loaded just return it, otherwise make a new skinframe
3771         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3772         if (skinframe->base)
3773                 return skinframe;
3774         textureflags &= ~TEXF_FORCE_RELOAD;
3775
3776         skinframe->stain = NULL;
3777         skinframe->merged = NULL;
3778         skinframe->base = NULL;
3779         skinframe->pants = NULL;
3780         skinframe->shirt = NULL;
3781         skinframe->nmap = NULL;
3782         skinframe->gloss = NULL;
3783         skinframe->glow = NULL;
3784         skinframe->fog = NULL;
3785         skinframe->reflect = NULL;
3786         skinframe->hasalpha = false;
3787
3788         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3789         if (!skindata)
3790                 return NULL;
3791
3792         if (developer_loading.integer)
3793                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3794
3795         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3796         if (textureflags & TEXF_ALPHA)
3797         {
3798                 for (i = 0;i < width * height;i++)
3799                 {
3800                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3801                         {
3802                                 skinframe->hasalpha = true;
3803                                 break;
3804                         }
3805                 }
3806                 if (r_loadfog && skinframe->hasalpha)
3807                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3808         }
3809
3810         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3811         //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]);
3812
3813         return skinframe;
3814 }
3815
3816 skinframe_t *R_SkinFrame_LoadMissing(void)
3817 {
3818         skinframe_t *skinframe;
3819
3820         if (cls.state == ca_dedicated)
3821                 return NULL;
3822
3823         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3824         skinframe->stain = NULL;
3825         skinframe->merged = NULL;
3826         skinframe->base = NULL;
3827         skinframe->pants = NULL;
3828         skinframe->shirt = NULL;
3829         skinframe->nmap = NULL;
3830         skinframe->gloss = NULL;
3831         skinframe->glow = NULL;
3832         skinframe->fog = NULL;
3833         skinframe->reflect = NULL;
3834         skinframe->hasalpha = false;
3835
3836         skinframe->avgcolor[0] = rand() / RAND_MAX;
3837         skinframe->avgcolor[1] = rand() / RAND_MAX;
3838         skinframe->avgcolor[2] = rand() / RAND_MAX;
3839         skinframe->avgcolor[3] = 1;
3840
3841         return skinframe;
3842 }
3843
3844 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3845 typedef struct suffixinfo_s
3846 {
3847         const char *suffix;
3848         qboolean flipx, flipy, flipdiagonal;
3849 }
3850 suffixinfo_t;
3851 static suffixinfo_t suffix[3][6] =
3852 {
3853         {
3854                 {"px",   false, false, false},
3855                 {"nx",   false, false, false},
3856                 {"py",   false, false, false},
3857                 {"ny",   false, false, false},
3858                 {"pz",   false, false, false},
3859                 {"nz",   false, false, false}
3860         },
3861         {
3862                 {"posx", false, false, false},
3863                 {"negx", false, false, false},
3864                 {"posy", false, false, false},
3865                 {"negy", false, false, false},
3866                 {"posz", false, false, false},
3867                 {"negz", false, false, false}
3868         },
3869         {
3870                 {"rt",    true, false,  true},
3871                 {"lf",   false,  true,  true},
3872                 {"ft",    true,  true, false},
3873                 {"bk",   false, false, false},
3874                 {"up",    true, false,  true},
3875                 {"dn",    true, false,  true}
3876         }
3877 };
3878
3879 static int componentorder[4] = {0, 1, 2, 3};
3880
3881 static rtexture_t *R_LoadCubemap(const char *basename)
3882 {
3883         int i, j, cubemapsize;
3884         unsigned char *cubemappixels, *image_buffer;
3885         rtexture_t *cubemaptexture;
3886         char name[256];
3887         // must start 0 so the first loadimagepixels has no requested width/height
3888         cubemapsize = 0;
3889         cubemappixels = NULL;
3890         cubemaptexture = NULL;
3891         // keep trying different suffix groups (posx, px, rt) until one loads
3892         for (j = 0;j < 3 && !cubemappixels;j++)
3893         {
3894                 // load the 6 images in the suffix group
3895                 for (i = 0;i < 6;i++)
3896                 {
3897                         // generate an image name based on the base and and suffix
3898                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3899                         // load it
3900                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3901                         {
3902                                 // an image loaded, make sure width and height are equal
3903                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3904                                 {
3905                                         // if this is the first image to load successfully, allocate the cubemap memory
3906                                         if (!cubemappixels && image_width >= 1)
3907                                         {
3908                                                 cubemapsize = image_width;
3909                                                 // note this clears to black, so unavailable sides are black
3910                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3911                                         }
3912                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3913                                         if (cubemappixels)
3914                                                 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);
3915                                 }
3916                                 else
3917                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3918                                 // free the image
3919                                 Mem_Free(image_buffer);
3920                         }
3921                 }
3922         }
3923         // if a cubemap loaded, upload it
3924         if (cubemappixels)
3925         {
3926                 if (developer_loading.integer)
3927                         Con_Printf("loading cubemap \"%s\"\n", basename);
3928
3929                 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);
3930                 Mem_Free(cubemappixels);
3931         }
3932         else
3933         {
3934                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3935                 if (developer_loading.integer)
3936                 {
3937                         Con_Printf("(tried tried images ");
3938                         for (j = 0;j < 3;j++)
3939                                 for (i = 0;i < 6;i++)
3940                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3941                         Con_Print(" and was unable to find any of them).\n");
3942                 }
3943         }
3944         return cubemaptexture;
3945 }
3946
3947 rtexture_t *R_GetCubemap(const char *basename)
3948 {
3949         int i;
3950         for (i = 0;i < r_texture_numcubemaps;i++)
3951                 if (r_texture_cubemaps[i] != NULL)
3952                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3953                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3954         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3955                 return r_texture_whitecube;
3956         r_texture_numcubemaps++;
3957         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3958         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3959         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3960         return r_texture_cubemaps[i]->texture;
3961 }
3962
3963 static void R_Main_FreeViewCache(void)
3964 {
3965         if (r_refdef.viewcache.entityvisible)
3966                 Mem_Free(r_refdef.viewcache.entityvisible);
3967         if (r_refdef.viewcache.world_pvsbits)
3968                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3969         if (r_refdef.viewcache.world_leafvisible)
3970                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3971         if (r_refdef.viewcache.world_surfacevisible)
3972                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3973         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3974 }
3975
3976 static void R_Main_ResizeViewCache(void)
3977 {
3978         int numentities = r_refdef.scene.numentities;
3979         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3980         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3981         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3982         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3983         if (r_refdef.viewcache.maxentities < numentities)
3984         {
3985                 r_refdef.viewcache.maxentities = numentities;
3986                 if (r_refdef.viewcache.entityvisible)
3987                         Mem_Free(r_refdef.viewcache.entityvisible);
3988                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3989         }
3990         if (r_refdef.viewcache.world_numclusters != numclusters)
3991         {
3992                 r_refdef.viewcache.world_numclusters = numclusters;
3993                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3994                 if (r_refdef.viewcache.world_pvsbits)
3995                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3996                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3997         }
3998         if (r_refdef.viewcache.world_numleafs != numleafs)
3999         {
4000                 r_refdef.viewcache.world_numleafs = numleafs;
4001                 if (r_refdef.viewcache.world_leafvisible)
4002                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4003                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4004         }
4005         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4006         {
4007                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4008                 if (r_refdef.viewcache.world_surfacevisible)
4009                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4010                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4011         }
4012 }
4013
4014 extern rtexture_t *loadingscreentexture;
4015 static void gl_main_start(void)
4016 {
4017         loadingscreentexture = NULL;
4018         r_texture_blanknormalmap = NULL;
4019         r_texture_white = NULL;
4020         r_texture_grey128 = NULL;
4021         r_texture_black = NULL;
4022         r_texture_whitecube = NULL;
4023         r_texture_normalizationcube = NULL;
4024         r_texture_fogattenuation = NULL;
4025         r_texture_fogheighttexture = NULL;
4026         r_texture_gammaramps = NULL;
4027         r_texture_numcubemaps = 0;
4028         r_uniformbufferalignment = 32;
4029
4030         r_loaddds = r_texture_dds_load.integer != 0;
4031         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4032
4033         switch(vid.renderpath)
4034         {
4035         case RENDERPATH_GL20:
4036         case RENDERPATH_D3D9:
4037         case RENDERPATH_D3D10:
4038         case RENDERPATH_D3D11:
4039         case RENDERPATH_SOFT:
4040         case RENDERPATH_GLES2:
4041                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4042                 Cvar_SetValueQuick(&gl_combine, 1);
4043                 Cvar_SetValueQuick(&r_glsl, 1);
4044                 r_loadnormalmap = true;
4045                 r_loadgloss = true;
4046                 r_loadfog = false;
4047 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4048                 if (vid.support.arb_uniform_buffer_object)
4049                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4050 #endif
4051                         break;
4052         case RENDERPATH_GL13:
4053         case RENDERPATH_GLES1:
4054                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4055                 Cvar_SetValueQuick(&gl_combine, 1);
4056                 Cvar_SetValueQuick(&r_glsl, 0);
4057                 r_loadnormalmap = false;
4058                 r_loadgloss = false;
4059                 r_loadfog = true;
4060                 break;
4061         case RENDERPATH_GL11:
4062                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4063                 Cvar_SetValueQuick(&gl_combine, 0);
4064                 Cvar_SetValueQuick(&r_glsl, 0);
4065                 r_loadnormalmap = false;
4066                 r_loadgloss = false;
4067                 r_loadfog = true;
4068                 break;
4069         }
4070
4071         R_AnimCache_Free();
4072         R_FrameData_Reset();
4073         R_BufferData_Reset();
4074
4075         r_numqueries = 0;
4076         r_maxqueries = 0;
4077         memset(r_queries, 0, sizeof(r_queries));
4078
4079         r_qwskincache = NULL;
4080         r_qwskincache_size = 0;
4081
4082         // due to caching of texture_t references, the collision cache must be reset
4083         Collision_Cache_Reset(true);
4084
4085         // set up r_skinframe loading system for textures
4086         memset(&r_skinframe, 0, sizeof(r_skinframe));
4087         r_skinframe.loadsequence = 1;
4088         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4089
4090         r_main_texturepool = R_AllocTexturePool();
4091         R_BuildBlankTextures();
4092         R_BuildNoTexture();
4093         if (vid.support.arb_texture_cube_map)
4094         {
4095                 R_BuildWhiteCube();
4096                 R_BuildNormalizationCube();
4097         }
4098         r_texture_fogattenuation = NULL;
4099         r_texture_fogheighttexture = NULL;
4100         r_texture_gammaramps = NULL;
4101         //r_texture_fogintensity = NULL;
4102         memset(&r_fb, 0, sizeof(r_fb));
4103         r_glsl_permutation = NULL;
4104         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4105         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4106         glslshaderstring = NULL;
4107 #ifdef SUPPORTD3D
4108         r_hlsl_permutation = NULL;
4109         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4110         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4111 #endif
4112         hlslshaderstring = NULL;
4113         memset(&r_svbsp, 0, sizeof (r_svbsp));
4114
4115         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4116         r_texture_numcubemaps = 0;
4117
4118         r_refdef.fogmasktable_density = 0;
4119
4120 #ifdef __ANDROID__
4121         // For Steelstorm Android
4122         // FIXME CACHE the program and reload
4123         // FIXME see possible combinations for SS:BR android
4124         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4125         R_SetupShader_SetPermutationGLSL(0, 12);
4126         R_SetupShader_SetPermutationGLSL(0, 13);
4127         R_SetupShader_SetPermutationGLSL(0, 8388621);
4128         R_SetupShader_SetPermutationGLSL(3, 0);
4129         R_SetupShader_SetPermutationGLSL(3, 2048);
4130         R_SetupShader_SetPermutationGLSL(5, 0);
4131         R_SetupShader_SetPermutationGLSL(5, 2);
4132         R_SetupShader_SetPermutationGLSL(5, 2048);
4133         R_SetupShader_SetPermutationGLSL(5, 8388608);
4134         R_SetupShader_SetPermutationGLSL(11, 1);
4135         R_SetupShader_SetPermutationGLSL(11, 2049);
4136         R_SetupShader_SetPermutationGLSL(11, 8193);
4137         R_SetupShader_SetPermutationGLSL(11, 10241);
4138         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4139 #endif
4140 }
4141
4142 static void gl_main_shutdown(void)
4143 {
4144         R_AnimCache_Free();
4145         R_FrameData_Reset();
4146         R_BufferData_Reset();
4147
4148         R_Main_FreeViewCache();
4149
4150         switch(vid.renderpath)
4151         {
4152         case RENDERPATH_GL11:
4153         case RENDERPATH_GL13:
4154         case RENDERPATH_GL20:
4155         case RENDERPATH_GLES1:
4156         case RENDERPATH_GLES2:
4157 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4158                 if (r_maxqueries)
4159                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4160 #endif
4161                 break;
4162         case RENDERPATH_D3D9:
4163                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4164                 break;
4165         case RENDERPATH_D3D10:
4166                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4167                 break;
4168         case RENDERPATH_D3D11:
4169                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4170                 break;
4171         case RENDERPATH_SOFT:
4172                 break;
4173         }
4174
4175         r_numqueries = 0;
4176         r_maxqueries = 0;
4177         memset(r_queries, 0, sizeof(r_queries));
4178
4179         r_qwskincache = NULL;
4180         r_qwskincache_size = 0;
4181
4182         // clear out the r_skinframe state
4183         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4184         memset(&r_skinframe, 0, sizeof(r_skinframe));
4185
4186         if (r_svbsp.nodes)
4187                 Mem_Free(r_svbsp.nodes);
4188         memset(&r_svbsp, 0, sizeof (r_svbsp));
4189         R_FreeTexturePool(&r_main_texturepool);
4190         loadingscreentexture = NULL;
4191         r_texture_blanknormalmap = NULL;
4192         r_texture_white = NULL;
4193         r_texture_grey128 = NULL;
4194         r_texture_black = NULL;
4195         r_texture_whitecube = NULL;
4196         r_texture_normalizationcube = NULL;
4197         r_texture_fogattenuation = NULL;
4198         r_texture_fogheighttexture = NULL;
4199         r_texture_gammaramps = NULL;
4200         r_texture_numcubemaps = 0;
4201         //r_texture_fogintensity = NULL;
4202         memset(&r_fb, 0, sizeof(r_fb));
4203         R_GLSL_Restart_f();
4204
4205         r_glsl_permutation = NULL;
4206         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4207         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4208         glslshaderstring = NULL;
4209 #ifdef SUPPORTD3D
4210         r_hlsl_permutation = NULL;
4211         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4212         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4213 #endif
4214         hlslshaderstring = NULL;
4215 }
4216
4217 static void gl_main_newmap(void)
4218 {
4219         // FIXME: move this code to client
4220         char *entities, entname[MAX_QPATH];
4221         if (r_qwskincache)
4222                 Mem_Free(r_qwskincache);
4223         r_qwskincache = NULL;
4224         r_qwskincache_size = 0;
4225         if (cl.worldmodel)
4226         {
4227                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4228                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4229                 {
4230                         CL_ParseEntityLump(entities);
4231                         Mem_Free(entities);
4232                         return;
4233                 }
4234                 if (cl.worldmodel->brush.entities)
4235                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4236         }
4237         R_Main_FreeViewCache();
4238
4239         R_FrameData_Reset();
4240         R_BufferData_Reset();
4241 }
4242
4243 void GL_Main_Init(void)
4244 {
4245         int i;
4246         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4247
4248         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4249         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4250         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4251         if (gamemode == GAME_NEHAHRA)
4252         {
4253                 Cvar_RegisterVariable (&gl_fogenable);
4254                 Cvar_RegisterVariable (&gl_fogdensity);
4255                 Cvar_RegisterVariable (&gl_fogred);
4256                 Cvar_RegisterVariable (&gl_foggreen);
4257                 Cvar_RegisterVariable (&gl_fogblue);
4258                 Cvar_RegisterVariable (&gl_fogstart);
4259                 Cvar_RegisterVariable (&gl_fogend);
4260                 Cvar_RegisterVariable (&gl_skyclip);
4261         }
4262         Cvar_RegisterVariable(&r_motionblur);
4263         Cvar_RegisterVariable(&r_damageblur);
4264         Cvar_RegisterVariable(&r_motionblur_averaging);
4265         Cvar_RegisterVariable(&r_motionblur_randomize);
4266         Cvar_RegisterVariable(&r_motionblur_minblur);
4267         Cvar_RegisterVariable(&r_motionblur_maxblur);
4268         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4269         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4270         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4271         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4272         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4273         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4274         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4275         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4276         Cvar_RegisterVariable(&r_equalize_entities_by);
4277         Cvar_RegisterVariable(&r_equalize_entities_to);
4278         Cvar_RegisterVariable(&r_depthfirst);
4279         Cvar_RegisterVariable(&r_useinfinitefarclip);
4280         Cvar_RegisterVariable(&r_farclip_base);
4281         Cvar_RegisterVariable(&r_farclip_world);
4282         Cvar_RegisterVariable(&r_nearclip);
4283         Cvar_RegisterVariable(&r_deformvertexes);
4284         Cvar_RegisterVariable(&r_transparent);
4285         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4286         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4287         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4288         Cvar_RegisterVariable(&r_showoverdraw);
4289         Cvar_RegisterVariable(&r_showbboxes);
4290         Cvar_RegisterVariable(&r_showsurfaces);
4291         Cvar_RegisterVariable(&r_showtris);
4292         Cvar_RegisterVariable(&r_shownormals);
4293         Cvar_RegisterVariable(&r_showlighting);
4294         Cvar_RegisterVariable(&r_showshadowvolumes);
4295         Cvar_RegisterVariable(&r_showcollisionbrushes);
4296         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4297         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4298         Cvar_RegisterVariable(&r_showdisabledepthtest);
4299         Cvar_RegisterVariable(&r_drawportals);
4300         Cvar_RegisterVariable(&r_drawentities);
4301         Cvar_RegisterVariable(&r_draw2d);
4302         Cvar_RegisterVariable(&r_drawworld);
4303         Cvar_RegisterVariable(&r_cullentities_trace);
4304         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4305         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4306         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4307         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4308         Cvar_RegisterVariable(&r_sortentities);
4309         Cvar_RegisterVariable(&r_drawviewmodel);
4310         Cvar_RegisterVariable(&r_drawexteriormodel);
4311         Cvar_RegisterVariable(&r_speeds);
4312         Cvar_RegisterVariable(&r_fullbrights);
4313         Cvar_RegisterVariable(&r_wateralpha);
4314         Cvar_RegisterVariable(&r_dynamic);
4315         Cvar_RegisterVariable(&r_fakelight);
4316         Cvar_RegisterVariable(&r_fakelight_intensity);
4317         Cvar_RegisterVariable(&r_fullbright);
4318         Cvar_RegisterVariable(&r_shadows);
4319         Cvar_RegisterVariable(&r_shadows_darken);
4320         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4321         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4322         Cvar_RegisterVariable(&r_shadows_throwdistance);
4323         Cvar_RegisterVariable(&r_shadows_throwdirection);
4324         Cvar_RegisterVariable(&r_shadows_focus);
4325         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4326         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4327         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4328         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4329         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4330         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4331         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4332         Cvar_RegisterVariable(&r_fog_exp2);
4333         Cvar_RegisterVariable(&r_fog_clear);
4334         Cvar_RegisterVariable(&r_drawfog);
4335         Cvar_RegisterVariable(&r_transparentdepthmasking);
4336         Cvar_RegisterVariable(&r_transparent_sortmindist);
4337         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4338         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4339         Cvar_RegisterVariable(&r_texture_dds_load);
4340         Cvar_RegisterVariable(&r_texture_dds_save);
4341         Cvar_RegisterVariable(&r_textureunits);
4342         Cvar_RegisterVariable(&gl_combine);
4343         Cvar_RegisterVariable(&r_usedepthtextures);
4344         Cvar_RegisterVariable(&r_viewfbo);
4345         Cvar_RegisterVariable(&r_viewscale);
4346         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4347         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4348         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4349         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4350         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4351         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4352         Cvar_RegisterVariable(&r_glsl);
4353         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4354         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4355         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4356         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4357         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4358         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4359         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4360         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4361         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4362         Cvar_RegisterVariable(&r_glsl_postprocess);
4363         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4364         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4365         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4366         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4367         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4368         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4369         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4370         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4371         Cvar_RegisterVariable(&r_celshading);
4372         Cvar_RegisterVariable(&r_celoutlines);
4373
4374         Cvar_RegisterVariable(&r_water);
4375         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4376         Cvar_RegisterVariable(&r_water_clippingplanebias);
4377         Cvar_RegisterVariable(&r_water_refractdistort);
4378         Cvar_RegisterVariable(&r_water_reflectdistort);
4379         Cvar_RegisterVariable(&r_water_scissormode);
4380         Cvar_RegisterVariable(&r_water_lowquality);
4381         Cvar_RegisterVariable(&r_water_hideplayer);
4382         Cvar_RegisterVariable(&r_water_fbo);
4383
4384         Cvar_RegisterVariable(&r_lerpsprites);
4385         Cvar_RegisterVariable(&r_lerpmodels);
4386         Cvar_RegisterVariable(&r_lerplightstyles);
4387         Cvar_RegisterVariable(&r_waterscroll);
4388         Cvar_RegisterVariable(&r_bloom);
4389         Cvar_RegisterVariable(&r_bloom_colorscale);
4390         Cvar_RegisterVariable(&r_bloom_brighten);
4391         Cvar_RegisterVariable(&r_bloom_blur);
4392         Cvar_RegisterVariable(&r_bloom_resolution);
4393         Cvar_RegisterVariable(&r_bloom_colorexponent);
4394         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4395         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4396         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4397         Cvar_RegisterVariable(&r_hdr_glowintensity);
4398         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4399         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4400         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4401         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4402         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4403         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4404         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4405         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4406         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4407         Cvar_RegisterVariable(&developer_texturelogging);
4408         Cvar_RegisterVariable(&gl_lightmaps);
4409         Cvar_RegisterVariable(&r_test);
4410         Cvar_RegisterVariable(&r_batch_multidraw);
4411         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4412         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4413         Cvar_RegisterVariable(&r_glsl_skeletal);
4414         Cvar_RegisterVariable(&r_glsl_saturation);
4415         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4416         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4417         Cvar_RegisterVariable(&r_framedatasize);
4418         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4419                 Cvar_RegisterVariable(&r_buffermegs[i]);
4420         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4421         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4422                 Cvar_SetValue("r_fullbrights", 0);
4423 #ifdef DP_MOBILETOUCH
4424         // GLES devices have terrible depth precision in general, so...
4425         Cvar_SetValueQuick(&r_nearclip, 4);
4426         Cvar_SetValueQuick(&r_farclip_base, 4096);
4427         Cvar_SetValueQuick(&r_farclip_world, 0);
4428         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4429 #endif
4430         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4431 }
4432
4433 void Render_Init(void)
4434 {
4435         gl_backend_init();
4436         R_Textures_Init();
4437         GL_Main_Init();
4438         Font_Init();
4439         GL_Draw_Init();
4440         R_Shadow_Init();
4441         R_Sky_Init();
4442         GL_Surf_Init();
4443         Sbar_Init();
4444         R_Particles_Init();
4445         R_Explosion_Init();
4446         R_LightningBeams_Init();
4447         Mod_RenderInit();
4448 }
4449
4450 /*
4451 ===============
4452 GL_Init
4453 ===============
4454 */
4455 #ifndef USE_GLES2
4456 extern char *ENGINE_EXTENSIONS;
4457 void GL_Init (void)
4458 {
4459         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4460         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4461         gl_version = (const char *)qglGetString(GL_VERSION);
4462         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4463
4464         if (!gl_extensions)
4465                 gl_extensions = "";
4466         if (!gl_platformextensions)
4467                 gl_platformextensions = "";
4468
4469         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4470         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4471         Con_Printf("GL_VERSION: %s\n", gl_version);
4472         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4473         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4474
4475         VID_CheckExtensions();
4476
4477         // LordHavoc: report supported extensions
4478 #ifdef CONFIG_MENU
4479         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4480 #else
4481         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4482 #endif
4483
4484         // clear to black (loading plaque will be seen over this)
4485         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4486 }
4487 #endif
4488
4489 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4490 {
4491         int i;
4492         mplane_t *p;
4493         if (r_trippy.integer)
4494                 return false;
4495         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4496         {
4497                 p = r_refdef.view.frustum + i;
4498                 switch(p->signbits)
4499                 {
4500                 default:
4501                 case 0:
4502                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4503                                 return true;
4504                         break;
4505                 case 1:
4506                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4507                                 return true;
4508                         break;
4509                 case 2:
4510                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4511                                 return true;
4512                         break;
4513                 case 3:
4514                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4515                                 return true;
4516                         break;
4517                 case 4:
4518                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4519                                 return true;
4520                         break;
4521                 case 5:
4522                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4523                                 return true;
4524                         break;
4525                 case 6:
4526                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4527                                 return true;
4528                         break;
4529                 case 7:
4530                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4531                                 return true;
4532                         break;
4533                 }
4534         }
4535         return false;
4536 }
4537
4538 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4539 {
4540         int i;
4541         const mplane_t *p;
4542         if (r_trippy.integer)
4543                 return false;
4544         for (i = 0;i < numplanes;i++)
4545         {
4546                 p = planes + i;
4547                 switch(p->signbits)
4548                 {
4549                 default:
4550                 case 0:
4551                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4552                                 return true;
4553                         break;
4554                 case 1:
4555                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4556                                 return true;
4557                         break;
4558                 case 2:
4559                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4560                                 return true;
4561                         break;
4562                 case 3:
4563                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4564                                 return true;
4565                         break;
4566                 case 4:
4567                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4568                                 return true;
4569                         break;
4570                 case 5:
4571                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4572                                 return true;
4573                         break;
4574                 case 6:
4575                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4576                                 return true;
4577                         break;
4578                 case 7:
4579                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4580                                 return true;
4581                         break;
4582                 }
4583         }
4584         return false;
4585 }
4586
4587 //==================================================================================
4588
4589 // LordHavoc: this stores temporary data used within the same frame
4590
4591 typedef struct r_framedata_mem_s
4592 {
4593         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4594         size_t size; // how much usable space
4595         size_t current; // how much space in use
4596         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4597         size_t wantedsize; // how much space was allocated
4598         unsigned char *data; // start of real data (16byte aligned)
4599 }
4600 r_framedata_mem_t;
4601
4602 static r_framedata_mem_t *r_framedata_mem;
4603
4604 void R_FrameData_Reset(void)
4605 {
4606         while (r_framedata_mem)
4607         {
4608                 r_framedata_mem_t *next = r_framedata_mem->purge;
4609                 Mem_Free(r_framedata_mem);
4610                 r_framedata_mem = next;
4611         }
4612 }
4613
4614 static void R_FrameData_Resize(qboolean mustgrow)
4615 {
4616         size_t wantedsize;
4617         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4618         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4619         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4620         {
4621                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4622                 newmem->wantedsize = wantedsize;
4623                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4624                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4625                 newmem->current = 0;
4626                 newmem->mark = 0;
4627                 newmem->purge = r_framedata_mem;
4628                 r_framedata_mem = newmem;
4629         }
4630 }
4631
4632 void R_FrameData_NewFrame(void)
4633 {
4634         R_FrameData_Resize(false);
4635         if (!r_framedata_mem)
4636                 return;
4637         // if we ran out of space on the last frame, free the old memory now
4638         while (r_framedata_mem->purge)
4639         {
4640                 // repeatedly remove the second item in the list, leaving only head
4641                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4642                 Mem_Free(r_framedata_mem->purge);
4643                 r_framedata_mem->purge = next;
4644         }
4645         // reset the current mem pointer
4646         r_framedata_mem->current = 0;
4647         r_framedata_mem->mark = 0;
4648 }
4649
4650 void *R_FrameData_Alloc(size_t size)
4651 {
4652         void *data;
4653         float newvalue;
4654
4655         // align to 16 byte boundary - the data pointer is already aligned, so we
4656         // only need to ensure the size of every allocation is also aligned
4657         size = (size + 15) & ~15;
4658
4659         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4660         {
4661                 // emergency - we ran out of space, allocate more memory
4662                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4663                 // this might not be a growing it, but we'll allocate another buffer every time
4664                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4665                 R_FrameData_Resize(true);
4666         }
4667
4668         data = r_framedata_mem->data + r_framedata_mem->current;
4669         r_framedata_mem->current += size;
4670
4671         // count the usage for stats
4672         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4673         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4674
4675         return (void *)data;
4676 }
4677
4678 void *R_FrameData_Store(size_t size, void *data)
4679 {
4680         void *d = R_FrameData_Alloc(size);
4681         if (d && data)
4682                 memcpy(d, data, size);
4683         return d;
4684 }
4685
4686 void R_FrameData_SetMark(void)
4687 {
4688         if (!r_framedata_mem)
4689                 return;
4690         r_framedata_mem->mark = r_framedata_mem->current;
4691 }
4692
4693 void R_FrameData_ReturnToMark(void)
4694 {
4695         if (!r_framedata_mem)
4696                 return;
4697         r_framedata_mem->current = r_framedata_mem->mark;
4698 }
4699
4700 //==================================================================================
4701
4702 // avoid reusing the same buffer objects on consecutive frames
4703 #define R_BUFFERDATA_CYCLE 3
4704
4705 typedef struct r_bufferdata_buffer_s
4706 {
4707         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4708         size_t size; // how much usable space
4709         size_t current; // how much space in use
4710         r_meshbuffer_t *buffer; // the buffer itself
4711 }
4712 r_bufferdata_buffer_t;
4713
4714 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4715 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4716
4717 /// frees all dynamic buffers
4718 void R_BufferData_Reset(void)
4719 {
4720         int cycle, type;
4721         r_bufferdata_buffer_t **p, *mem;
4722         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4723         {
4724                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4725                 {
4726                         // free all buffers
4727                         p = &r_bufferdata_buffer[cycle][type];
4728                         while (*p)
4729                         {
4730                                 mem = *p;
4731                                 *p = (*p)->purge;
4732                                 if (mem->buffer)
4733                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4734                                 Mem_Free(mem);
4735                         }
4736                 }
4737         }
4738 }
4739
4740 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4741 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4742 {
4743         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4744         size_t size;
4745         float newvalue = r_buffermegs[type].value;
4746
4747         // increase the cvar if we have to (but only if we already have a mem)
4748         if (mustgrow && mem)
4749                 newvalue *= 2.0f;
4750         newvalue = bound(0.25f, newvalue, 256.0f);
4751         while (newvalue * 1024*1024 < minsize)
4752                 newvalue *= 2.0f;
4753
4754         // clamp the cvar to valid range
4755         newvalue = bound(0.25f, newvalue, 256.0f);
4756         if (r_buffermegs[type].value != newvalue)
4757                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4758
4759         // calculate size in bytes
4760         size = (size_t)(newvalue * 1024*1024);
4761         size = bound(131072, size, 256*1024*1024);
4762
4763         // allocate a new buffer if the size is different (purge old one later)
4764         // or if we were told we must grow the buffer
4765         if (!mem || mem->size != size || mustgrow)
4766         {
4767                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4768                 mem->size = size;
4769                 mem->current = 0;
4770                 if (type == R_BUFFERDATA_VERTEX)
4771                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4772                 else if (type == R_BUFFERDATA_INDEX16)
4773                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4774                 else if (type == R_BUFFERDATA_INDEX32)
4775                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4776                 else if (type == R_BUFFERDATA_UNIFORM)
4777                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4778                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4779                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4780         }
4781 }
4782
4783 void R_BufferData_NewFrame(void)
4784 {
4785         int type;
4786         r_bufferdata_buffer_t **p, *mem;
4787         // cycle to the next frame's buffers
4788         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4789         // if we ran out of space on the last time we used these buffers, free the old memory now
4790         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4791         {
4792                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4793                 {
4794                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4795                         // free all but the head buffer, this is how we recycle obsolete
4796                         // buffers after they are no longer in use
4797                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4798                         while (*p)
4799                         {
4800                                 mem = *p;
4801                                 *p = (*p)->purge;
4802                                 if (mem->buffer)
4803                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4804                                 Mem_Free(mem);
4805                         }
4806                         // reset the current offset
4807                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4808                 }
4809         }
4810 }
4811
4812 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4813 {
4814         r_bufferdata_buffer_t *mem;
4815         int offset = 0;
4816         int padsize;
4817
4818         *returnbufferoffset = 0;
4819
4820         // align size to a byte boundary appropriate for the buffer type, this
4821         // makes all allocations have aligned start offsets
4822         if (type == R_BUFFERDATA_UNIFORM)
4823                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4824         else
4825                 padsize = (datasize + 15) & ~15;
4826
4827         // if we ran out of space in this buffer we must allocate a new one
4828         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)
4829                 R_BufferData_Resize(type, true, padsize);
4830
4831         // if the resize did not give us enough memory, fail
4832         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)
4833                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4834
4835         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4836         offset = (int)mem->current;
4837         mem->current += padsize;
4838
4839         // upload the data to the buffer at the chosen offset
4840         if (offset == 0)
4841                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4842         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4843
4844         // count the usage for stats
4845         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4846         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4847
4848         // return the buffer offset
4849         *returnbufferoffset = offset;
4850
4851         return mem->buffer;
4852 }
4853
4854 //==================================================================================
4855
4856 // LordHavoc: animcache originally written by Echon, rewritten since then
4857
4858 /**
4859  * Animation cache prevents re-generating mesh data for an animated model
4860  * multiple times in one frame for lighting, shadowing, reflections, etc.
4861  */
4862
4863 void R_AnimCache_Free(void)
4864 {
4865 }
4866
4867 void R_AnimCache_ClearCache(void)
4868 {
4869         int i;
4870         entity_render_t *ent;
4871
4872         for (i = 0;i < r_refdef.scene.numentities;i++)
4873         {
4874                 ent = r_refdef.scene.entities[i];
4875                 ent->animcache_vertex3f = NULL;
4876                 ent->animcache_vertex3f_vertexbuffer = NULL;
4877                 ent->animcache_vertex3f_bufferoffset = 0;
4878                 ent->animcache_normal3f = NULL;
4879                 ent->animcache_normal3f_vertexbuffer = NULL;
4880                 ent->animcache_normal3f_bufferoffset = 0;
4881                 ent->animcache_svector3f = NULL;
4882                 ent->animcache_svector3f_vertexbuffer = NULL;
4883                 ent->animcache_svector3f_bufferoffset = 0;
4884                 ent->animcache_tvector3f = NULL;
4885                 ent->animcache_tvector3f_vertexbuffer = NULL;
4886                 ent->animcache_tvector3f_bufferoffset = 0;
4887                 ent->animcache_vertexmesh = NULL;
4888                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4889                 ent->animcache_vertexmesh_bufferoffset = 0;
4890                 ent->animcache_skeletaltransform3x4 = NULL;
4891                 ent->animcache_skeletaltransform3x4buffer = NULL;
4892                 ent->animcache_skeletaltransform3x4offset = 0;
4893                 ent->animcache_skeletaltransform3x4size = 0;
4894         }
4895 }
4896
4897 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4898 {
4899         int i;
4900
4901         // check if we need the meshbuffers
4902         if (!vid.useinterleavedarrays)
4903                 return;
4904
4905         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4906                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4907         // TODO: upload vertexbuffer?
4908         if (ent->animcache_vertexmesh)
4909         {
4910                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4911                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4912                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4913                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4914                 for (i = 0;i < numvertices;i++)
4915                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4916                 if (ent->animcache_svector3f)
4917                         for (i = 0;i < numvertices;i++)
4918                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4919                 if (ent->animcache_tvector3f)
4920                         for (i = 0;i < numvertices;i++)
4921                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4922                 if (ent->animcache_normal3f)
4923                         for (i = 0;i < numvertices;i++)
4924                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4925         }
4926 }
4927
4928 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4929 {
4930         dp_model_t *model = ent->model;
4931         int numvertices;
4932
4933         // see if this ent is worth caching
4934         if (!model || !model->Draw || !model->AnimateVertices)
4935                 return false;
4936         // nothing to cache if it contains no animations and has no skeleton
4937         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4938                 return false;
4939         // see if it is already cached for gpuskeletal
4940         if (ent->animcache_skeletaltransform3x4)
4941                 return false;
4942         // see if it is already cached as a mesh
4943         if (ent->animcache_vertex3f)
4944         {
4945                 // check if we need to add normals or tangents
4946                 if (ent->animcache_normal3f)
4947                         wantnormals = false;
4948                 if (ent->animcache_svector3f)
4949                         wanttangents = false;
4950                 if (!wantnormals && !wanttangents)
4951                         return false;
4952         }
4953
4954         // check which kind of cache we need to generate
4955         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4956         {
4957                 // cache the skeleton so the vertex shader can use it
4958                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4959                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4960                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4961                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4962                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4963                 // note: this can fail if the buffer is at the grow limit
4964                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4965                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4966         }
4967         else if (ent->animcache_vertex3f)
4968         {
4969                 // mesh was already cached but we may need to add normals/tangents
4970                 // (this only happens with multiple views, reflections, cameras, etc)
4971                 if (wantnormals || wanttangents)
4972                 {
4973                         numvertices = model->surfmesh.num_vertices;
4974                         if (wantnormals)
4975                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4976                         if (wanttangents)
4977                         {
4978                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4979                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4980                         }
4981                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4982                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4983                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4984                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4985                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4986                 }
4987         }
4988         else
4989         {
4990                 // generate mesh cache
4991                 numvertices = model->surfmesh.num_vertices;
4992                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4993                 if (wantnormals)
4994                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4995                 if (wanttangents)
4996                 {
4997                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4998                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4999                 }
5000                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5001                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5002                 if (wantnormals || wanttangents)
5003                 {
5004                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5005                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5006                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5007                 }
5008                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5009                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5010                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5011         }
5012         return true;
5013 }
5014
5015 void R_AnimCache_CacheVisibleEntities(void)
5016 {
5017         int i;
5018         qboolean wantnormals = true;
5019         qboolean wanttangents = !r_showsurfaces.integer;
5020
5021         switch(vid.renderpath)
5022         {
5023         case RENDERPATH_GL20:
5024         case RENDERPATH_D3D9:
5025         case RENDERPATH_D3D10:
5026         case RENDERPATH_D3D11:
5027         case RENDERPATH_GLES2:
5028                 break;
5029         case RENDERPATH_GL11:
5030         case RENDERPATH_GL13:
5031         case RENDERPATH_GLES1:
5032                 wanttangents = false;
5033                 break;
5034         case RENDERPATH_SOFT:
5035                 break;
5036         }
5037
5038         if (r_shownormals.integer)
5039                 wanttangents = wantnormals = true;
5040
5041         // TODO: thread this
5042         // NOTE: R_PrepareRTLights() also caches entities
5043
5044         for (i = 0;i < r_refdef.scene.numentities;i++)
5045                 if (r_refdef.viewcache.entityvisible[i])
5046                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5047 }
5048
5049 //==================================================================================
5050
5051 extern cvar_t r_overheadsprites_pushback;
5052
5053 static void R_View_UpdateEntityLighting (void)
5054 {
5055         int i;
5056         entity_render_t *ent;
5057         vec3_t tempdiffusenormal, avg;
5058         vec_t f, fa, fd, fdd;
5059         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5060
5061         for (i = 0;i < r_refdef.scene.numentities;i++)
5062         {
5063                 ent = r_refdef.scene.entities[i];
5064
5065                 // skip unseen models
5066                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5067                         continue;
5068
5069                 // skip bsp models
5070                 if (ent->model && ent->model == cl.worldmodel)
5071                 {
5072                         // TODO: use modellight for r_ambient settings on world?
5073                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5074                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5075                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5076                         continue;
5077                 }
5078                 
5079                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5080                 {
5081                         // aleady updated by CSQC
5082                         // TODO: force modellight on BSP models in this case?
5083                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5084                 }
5085                 else
5086                 {
5087                         // fetch the lighting from the worldmodel data
5088                         VectorClear(ent->modellight_ambient);
5089                         VectorClear(ent->modellight_diffuse);
5090                         VectorClear(tempdiffusenormal);
5091                         if (ent->flags & RENDER_LIGHT)
5092                         {
5093                                 vec3_t org;
5094                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5095
5096                                 // complete lightning for lit sprites
5097                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5098                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5099                                 {
5100                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5101                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5102                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5103                                 }
5104                                 else
5105                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5106
5107                                 if(ent->flags & RENDER_EQUALIZE)
5108                                 {
5109                                         // first fix up ambient lighting...
5110                                         if(r_equalize_entities_minambient.value > 0)
5111                                         {
5112                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5113                                                 if(fd > 0)
5114                                                 {
5115                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5116                                                         if(fa < r_equalize_entities_minambient.value * fd)
5117                                                         {
5118                                                                 // solve:
5119                                                                 //   fa'/fd' = minambient
5120                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5121                                                                 //   ...
5122                                                                 //   fa' = fd' * minambient
5123                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5124                                                                 //   ...
5125                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5126                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5127                                                                 //   ...
5128                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5129                                                                 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
5130                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5131                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5132                                                         }
5133                                                 }
5134                                         }
5135
5136                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5137                                         {
5138                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5139                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5140                                                 f = fa + 0.25 * fd;
5141                                                 if(f > 0)
5142                                                 {
5143                                                         // adjust brightness and saturation to target
5144                                                         avg[0] = avg[1] = avg[2] = fa / f;
5145                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5146                                                         avg[0] = avg[1] = avg[2] = fd / f;
5147                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5148                                                 }
5149                                         }
5150                                 }
5151                         }
5152                         else // highly rare
5153                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5154                 }
5155
5156                 // move the light direction into modelspace coordinates for lighting code
5157                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5158                 if(VectorLength2(ent->modellight_lightdir) == 0)
5159                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5160                 VectorNormalize(ent->modellight_lightdir);
5161         }
5162 }
5163
5164 #define MAX_LINEOFSIGHTTRACES 64
5165
5166 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5167 {
5168         int i;
5169         vec3_t boxmins, boxmaxs;
5170         vec3_t start;
5171         vec3_t end;
5172         dp_model_t *model = r_refdef.scene.worldmodel;
5173
5174         if (!model || !model->brush.TraceLineOfSight)
5175                 return true;
5176
5177         // expand the box a little
5178         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5179         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5180         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5181         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5182         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5183         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5184
5185         // return true if eye is inside enlarged box
5186         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5187                 return true;
5188
5189         // try center
5190         VectorCopy(eye, start);
5191         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5192         if (model->brush.TraceLineOfSight(model, start, end))
5193                 return true;
5194
5195         // try various random positions
5196         for (i = 0;i < numsamples;i++)
5197         {
5198                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5199                 if (model->brush.TraceLineOfSight(model, start, end))
5200                         return true;
5201         }
5202
5203         return false;
5204 }
5205
5206
5207 static void R_View_UpdateEntityVisible (void)
5208 {
5209         int i;
5210         int renderimask;
5211         int samples;
5212         entity_render_t *ent;
5213
5214         if (r_refdef.envmap || r_fb.water.hideplayer)
5215                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5216         else if (chase_active.integer || r_fb.water.renderingscene)
5217                 renderimask = RENDER_VIEWMODEL;
5218         else
5219                 renderimask = RENDER_EXTERIORMODEL;
5220         if (!r_drawviewmodel.integer)
5221                 renderimask |= RENDER_VIEWMODEL;
5222         if (!r_drawexteriormodel.integer)
5223                 renderimask |= RENDER_EXTERIORMODEL;
5224         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5225         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5226         {
5227                 // worldmodel can check visibility
5228                 for (i = 0;i < r_refdef.scene.numentities;i++)
5229                 {
5230                         ent = r_refdef.scene.entities[i];
5231                         if (!(ent->flags & renderimask))
5232                         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)))
5233                         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))
5234                                 r_refdef.viewcache.entityvisible[i] = true;
5235                 }
5236         }
5237         else
5238         {
5239                 // no worldmodel or it can't check visibility
5240                 for (i = 0;i < r_refdef.scene.numentities;i++)
5241                 {
5242                         ent = r_refdef.scene.entities[i];
5243                         if (!(ent->flags & renderimask))
5244                         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)))
5245                                 r_refdef.viewcache.entityvisible[i] = true;
5246                 }
5247         }
5248         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5249                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5250         {
5251                 for (i = 0;i < r_refdef.scene.numentities;i++)
5252                 {
5253                         if (!r_refdef.viewcache.entityvisible[i])
5254                                 continue;
5255                         ent = r_refdef.scene.entities[i];
5256                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5257                         {
5258                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5259                                 if (samples < 0)
5260                                         continue; // temp entities do pvs only
5261                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5262                                         ent->last_trace_visibility = realtime;
5263                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5264                                         r_refdef.viewcache.entityvisible[i] = 0;
5265                         }
5266                 }
5267         }
5268 }
5269
5270 /// only used if skyrendermasked, and normally returns false
5271 static int R_DrawBrushModelsSky (void)
5272 {
5273         int i, sky;
5274         entity_render_t *ent;
5275
5276         sky = false;
5277         for (i = 0;i < r_refdef.scene.numentities;i++)
5278         {
5279                 if (!r_refdef.viewcache.entityvisible[i])
5280                         continue;
5281                 ent = r_refdef.scene.entities[i];
5282                 if (!ent->model || !ent->model->DrawSky)
5283                         continue;
5284                 ent->model->DrawSky(ent);
5285                 sky = true;
5286         }
5287         return sky;
5288 }
5289
5290 static void R_DrawNoModel(entity_render_t *ent);
5291 static void R_DrawModels(void)
5292 {
5293         int i;
5294         entity_render_t *ent;
5295
5296         for (i = 0;i < r_refdef.scene.numentities;i++)
5297         {
5298                 if (!r_refdef.viewcache.entityvisible[i])
5299                         continue;
5300                 ent = r_refdef.scene.entities[i];
5301                 r_refdef.stats[r_stat_entities]++;
5302                 /*
5303                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5304                 {
5305                         vec3_t f, l, u, o;
5306                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5307                         Con_Printf("R_DrawModels\n");
5308                         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]);
5309                         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);
5310                         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);
5311                 }
5312                 */
5313                 if (ent->model && ent->model->Draw != NULL)
5314                         ent->model->Draw(ent);
5315                 else
5316                         R_DrawNoModel(ent);
5317         }
5318 }
5319
5320 static void R_DrawModelsDepth(void)
5321 {
5322         int i;
5323         entity_render_t *ent;
5324
5325         for (i = 0;i < r_refdef.scene.numentities;i++)
5326         {
5327                 if (!r_refdef.viewcache.entityvisible[i])
5328                         continue;
5329                 ent = r_refdef.scene.entities[i];
5330                 if (ent->model && ent->model->DrawDepth != NULL)
5331                         ent->model->DrawDepth(ent);
5332         }
5333 }
5334
5335 static void R_DrawModelsDebug(void)
5336 {
5337         int i;
5338         entity_render_t *ent;
5339
5340         for (i = 0;i < r_refdef.scene.numentities;i++)
5341         {
5342                 if (!r_refdef.viewcache.entityvisible[i])
5343                         continue;
5344                 ent = r_refdef.scene.entities[i];
5345                 if (ent->model && ent->model->DrawDebug != NULL)
5346                         ent->model->DrawDebug(ent);
5347         }
5348 }
5349
5350 static void R_DrawModelsAddWaterPlanes(void)
5351 {
5352         int i;
5353         entity_render_t *ent;
5354
5355         for (i = 0;i < r_refdef.scene.numentities;i++)
5356         {
5357                 if (!r_refdef.viewcache.entityvisible[i])
5358                         continue;
5359                 ent = r_refdef.scene.entities[i];
5360                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5361                         ent->model->DrawAddWaterPlanes(ent);
5362         }
5363 }
5364
5365 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}};
5366
5367 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5368 {
5369         if (r_hdr_irisadaptation.integer)
5370         {
5371                 vec3_t p;
5372                 vec3_t ambient;
5373                 vec3_t diffuse;
5374                 vec3_t diffusenormal;
5375                 vec3_t forward;
5376                 vec_t brightness = 0.0f;
5377                 vec_t goal;
5378                 vec_t current;
5379                 vec_t d;
5380                 int c;
5381                 VectorCopy(r_refdef.view.forward, forward);
5382                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5383                 {
5384                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5385                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5386                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5387                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5388                         d = DotProduct(forward, diffusenormal);
5389                         brightness += VectorLength(ambient);
5390                         if (d > 0)
5391                                 brightness += d * VectorLength(diffuse);
5392                 }
5393                 brightness *= 1.0f / c;
5394                 brightness += 0.00001f; // make sure it's never zero
5395                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5396                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5397                 current = r_hdr_irisadaptation_value.value;
5398                 if (current < goal)
5399                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5400                 else if (current > goal)
5401                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5402                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5403                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5404         }
5405         else if (r_hdr_irisadaptation_value.value != 1.0f)
5406                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5407 }
5408
5409 static void R_View_SetFrustum(const int *scissor)
5410 {
5411         int i;
5412         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5413         vec3_t forward, left, up, origin, v;
5414
5415         if(scissor)
5416         {
5417                 // flipped x coordinates (because x points left here)
5418                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5419                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5420
5421                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5422                 switch(vid.renderpath)
5423                 {
5424                         case RENDERPATH_D3D9:
5425                         case RENDERPATH_D3D10:
5426                         case RENDERPATH_D3D11:
5427                                 // non-flipped y coordinates
5428                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5429                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5430                                 break;
5431                         case RENDERPATH_SOFT:
5432                         case RENDERPATH_GL11:
5433                         case RENDERPATH_GL13:
5434                         case RENDERPATH_GL20:
5435                         case RENDERPATH_GLES1:
5436                         case RENDERPATH_GLES2:
5437                                 // non-flipped y coordinates
5438                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5439                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5440                                 break;
5441                 }
5442         }
5443
5444         // we can't trust r_refdef.view.forward and friends in reflected scenes
5445         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5446
5447 #if 0
5448         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5449         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5450         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5451         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5452         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5453         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5454         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5455         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5456         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5457         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5458         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5459         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5460 #endif
5461
5462 #if 0
5463         zNear = r_refdef.nearclip;
5464         nudge = 1.0 - 1.0 / (1<<23);
5465         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5466         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5467         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5468         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5469         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5470         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5471         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5472         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5473 #endif
5474
5475
5476
5477 #if 0
5478         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5479         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5480         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5481         r_refdef.view.frustum[0].dist = m[15] - m[12];
5482
5483         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5484         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5485         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5486         r_refdef.view.frustum[1].dist = m[15] + m[12];
5487
5488         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5489         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5490         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5491         r_refdef.view.frustum[2].dist = m[15] - m[13];
5492
5493         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5494         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5495         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5496         r_refdef.view.frustum[3].dist = m[15] + m[13];
5497
5498         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5499         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5500         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5501         r_refdef.view.frustum[4].dist = m[15] - m[14];
5502
5503         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5504         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5505         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5506         r_refdef.view.frustum[5].dist = m[15] + m[14];
5507 #endif
5508
5509         if (r_refdef.view.useperspective)
5510         {
5511                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5512                 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]);
5513                 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]);
5514                 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]);
5515                 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]);
5516
5517                 // then the normals from the corners relative to origin
5518                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5519                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5520                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5521                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5522
5523                 // in a NORMAL view, forward cross left == up
5524                 // in a REFLECTED view, forward cross left == down
5525                 // so our cross products above need to be adjusted for a left handed coordinate system
5526                 CrossProduct(forward, left, v);
5527                 if(DotProduct(v, up) < 0)
5528                 {
5529                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5530                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5531                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5532                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5533                 }
5534
5535                 // Leaving those out was a mistake, those were in the old code, and they
5536                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5537                 // I couldn't reproduce it after adding those normalizations. --blub
5538                 VectorNormalize(r_refdef.view.frustum[0].normal);
5539                 VectorNormalize(r_refdef.view.frustum[1].normal);
5540                 VectorNormalize(r_refdef.view.frustum[2].normal);
5541                 VectorNormalize(r_refdef.view.frustum[3].normal);
5542
5543                 // make the corners absolute
5544                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5545                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5546                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5547                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5548
5549                 // one more normal
5550                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5551
5552                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5553                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5554                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5555                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5556                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5557         }
5558         else
5559         {
5560                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5561                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5562                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5563                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5564                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5565                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5566                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5567                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5568                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5569                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5570         }
5571         r_refdef.view.numfrustumplanes = 5;
5572
5573         if (r_refdef.view.useclipplane)
5574         {
5575                 r_refdef.view.numfrustumplanes = 6;
5576                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5577         }
5578
5579         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5580                 PlaneClassify(r_refdef.view.frustum + i);
5581
5582         // LordHavoc: note to all quake engine coders, Quake had a special case
5583         // for 90 degrees which assumed a square view (wrong), so I removed it,
5584         // Quake2 has it disabled as well.
5585
5586         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5587         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5588         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5589         //PlaneClassify(&frustum[0]);
5590
5591         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5592         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5593         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5594         //PlaneClassify(&frustum[1]);
5595
5596         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5597         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5598         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5599         //PlaneClassify(&frustum[2]);
5600
5601         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5602         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5603         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5604         //PlaneClassify(&frustum[3]);
5605
5606         // nearclip plane
5607         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5608         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5609         //PlaneClassify(&frustum[4]);
5610 }
5611
5612 static void R_View_UpdateWithScissor(const int *myscissor)
5613 {
5614         R_Main_ResizeViewCache();
5615         R_View_SetFrustum(myscissor);
5616         R_View_WorldVisibility(r_refdef.view.useclipplane);
5617         R_View_UpdateEntityVisible();
5618         R_View_UpdateEntityLighting();
5619 }
5620
5621 static void R_View_Update(void)
5622 {
5623         R_Main_ResizeViewCache();
5624         R_View_SetFrustum(NULL);
5625         R_View_WorldVisibility(r_refdef.view.useclipplane);
5626         R_View_UpdateEntityVisible();
5627         R_View_UpdateEntityLighting();
5628 }
5629
5630 float viewscalefpsadjusted = 1.0f;
5631
5632 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5633 {
5634         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5635         scale = bound(0.03125f, scale, 1.0f);
5636         *outwidth = (int)ceil(width * scale);
5637         *outheight = (int)ceil(height * scale);
5638 }
5639
5640 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5641 {
5642         const float *customclipplane = NULL;
5643         float plane[4];
5644         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5645         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5646         {
5647                 // LordHavoc: couldn't figure out how to make this approach the
5648                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5649                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5650                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5651                         dist = r_refdef.view.clipplane.dist;
5652                 plane[0] = r_refdef.view.clipplane.normal[0];
5653                 plane[1] = r_refdef.view.clipplane.normal[1];
5654                 plane[2] = r_refdef.view.clipplane.normal[2];
5655                 plane[3] = -dist;
5656                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5657         }
5658
5659         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5660         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5661
5662         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5663         if (!r_refdef.view.useperspective)
5664                 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);
5665         else if (vid.stencil && r_useinfinitefarclip.integer)
5666                 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);
5667         else
5668                 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);
5669         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5670         R_SetViewport(&r_refdef.view.viewport);
5671         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5672         {
5673                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5674                 float screenplane[4];
5675                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5676                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5677                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5678                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5679                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5680         }
5681 }
5682
5683 void R_EntityMatrix(const matrix4x4_t *matrix)
5684 {
5685         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5686         {
5687                 gl_modelmatrixchanged = false;
5688                 gl_modelmatrix = *matrix;
5689                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5690                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5691                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5692                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5693                 CHECKGLERROR
5694                 switch(vid.renderpath)
5695                 {
5696                 case RENDERPATH_D3D9:
5697 #ifdef SUPPORTD3D
5698                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5699                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5700 #endif
5701                         break;
5702                 case RENDERPATH_D3D10:
5703                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5704                         break;
5705                 case RENDERPATH_D3D11:
5706                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5707                         break;
5708                 case RENDERPATH_GL11:
5709                 case RENDERPATH_GL13:
5710                 case RENDERPATH_GLES1:
5711 #ifndef USE_GLES2
5712                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5713 #endif
5714                         break;
5715                 case RENDERPATH_SOFT:
5716                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5717                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5718                         break;
5719                 case RENDERPATH_GL20:
5720                 case RENDERPATH_GLES2:
5721                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5722                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5723                         break;
5724                 }
5725         }
5726 }
5727
5728 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5729 {
5730         r_viewport_t viewport;
5731
5732         CHECKGLERROR
5733
5734         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5735         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);
5736         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5737         R_SetViewport(&viewport);
5738         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5739         GL_Color(1, 1, 1, 1);
5740         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5741         GL_BlendFunc(GL_ONE, GL_ZERO);
5742         GL_ScissorTest(false);
5743         GL_DepthMask(false);
5744         GL_DepthRange(0, 1);
5745         GL_DepthTest(false);
5746         GL_DepthFunc(GL_LEQUAL);
5747         R_EntityMatrix(&identitymatrix);
5748         R_Mesh_ResetTextureState();
5749         GL_PolygonOffset(0, 0);
5750         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5751         switch(vid.renderpath)
5752         {
5753         case RENDERPATH_GL11:
5754         case RENDERPATH_GL13:
5755         case RENDERPATH_GL20:
5756         case RENDERPATH_GLES1:
5757         case RENDERPATH_GLES2:
5758                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5759                 break;
5760         case RENDERPATH_D3D9:
5761         case RENDERPATH_D3D10:
5762         case RENDERPATH_D3D11:
5763         case RENDERPATH_SOFT:
5764                 break;
5765         }
5766         GL_CullFace(GL_NONE);
5767
5768         CHECKGLERROR
5769 }
5770
5771 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5772 {
5773         DrawQ_Finish();
5774
5775         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5776 }
5777
5778 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5779 {
5780         DrawQ_Finish();
5781
5782         R_SetupView(true, fbo, depthtexture, colortexture);
5783         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5784         GL_Color(1, 1, 1, 1);
5785         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5786         GL_BlendFunc(GL_ONE, GL_ZERO);
5787         GL_ScissorTest(true);
5788         GL_DepthMask(true);
5789         GL_DepthRange(0, 1);
5790         GL_DepthTest(true);
5791         GL_DepthFunc(GL_LEQUAL);
5792         R_EntityMatrix(&identitymatrix);
5793         R_Mesh_ResetTextureState();
5794         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5795         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5796         switch(vid.renderpath)
5797         {
5798         case RENDERPATH_GL11:
5799         case RENDERPATH_GL13:
5800         case RENDERPATH_GL20:
5801         case RENDERPATH_GLES1:
5802         case RENDERPATH_GLES2:
5803                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5804                 break;
5805         case RENDERPATH_D3D9:
5806         case RENDERPATH_D3D10:
5807         case RENDERPATH_D3D11:
5808         case RENDERPATH_SOFT:
5809                 break;
5810         }
5811         GL_CullFace(r_refdef.view.cullface_back);
5812 }
5813
5814 /*
5815 ================
5816 R_RenderView_UpdateViewVectors
5817 ================
5818 */
5819 void R_RenderView_UpdateViewVectors(void)
5820 {
5821         // break apart the view matrix into vectors for various purposes
5822         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5823         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5824         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5825         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5826         // make an inverted copy of the view matrix for tracking sprites
5827         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5828 }
5829
5830 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5831 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5832
5833 static void R_Water_StartFrame(void)
5834 {
5835         int i;
5836         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5837         r_waterstate_waterplane_t *p;
5838         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;
5839
5840         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5841                 return;
5842
5843         switch(vid.renderpath)
5844         {
5845         case RENDERPATH_GL20:
5846         case RENDERPATH_D3D9:
5847         case RENDERPATH_D3D10:
5848         case RENDERPATH_D3D11:
5849         case RENDERPATH_SOFT:
5850         case RENDERPATH_GLES2:
5851                 break;
5852         case RENDERPATH_GL11:
5853         case RENDERPATH_GL13:
5854         case RENDERPATH_GLES1:
5855                 return;
5856         }
5857
5858         // set waterwidth and waterheight to the water resolution that will be
5859         // used (often less than the screen resolution for faster rendering)
5860         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5861
5862         // calculate desired texture sizes
5863         // can't use water if the card does not support the texture size
5864         if (!r_water.integer || r_showsurfaces.integer)
5865                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5866         else if (vid.support.arb_texture_non_power_of_two)
5867         {
5868                 texturewidth = waterwidth;
5869                 textureheight = waterheight;
5870                 camerawidth = waterwidth;
5871                 cameraheight = waterheight;
5872         }
5873         else
5874         {
5875                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5876                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5877                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5878                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5879         }
5880
5881         // allocate textures as needed
5882         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))
5883         {
5884                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5885                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5886                 {
5887                         if (p->texture_refraction)
5888                                 R_FreeTexture(p->texture_refraction);
5889                         p->texture_refraction = NULL;
5890                         if (p->fbo_refraction)
5891                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5892                         p->fbo_refraction = 0;
5893                         if (p->texture_reflection)
5894                                 R_FreeTexture(p->texture_reflection);
5895                         p->texture_reflection = NULL;
5896                         if (p->fbo_reflection)
5897                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5898                         p->fbo_reflection = 0;
5899                         if (p->texture_camera)
5900                                 R_FreeTexture(p->texture_camera);
5901                         p->texture_camera = NULL;
5902                         if (p->fbo_camera)
5903                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5904                         p->fbo_camera = 0;
5905                 }
5906                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5907                 r_fb.water.texturewidth = texturewidth;
5908                 r_fb.water.textureheight = textureheight;
5909                 r_fb.water.camerawidth = camerawidth;
5910                 r_fb.water.cameraheight = cameraheight;
5911         }
5912
5913         if (r_fb.water.texturewidth)
5914         {
5915                 int scaledwidth, scaledheight;
5916
5917                 r_fb.water.enabled = true;
5918
5919                 // water resolution is usually reduced
5920                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5921                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5922                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5923
5924                 // set up variables that will be used in shader setup
5925                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5926                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5927                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5928                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5929         }
5930
5931         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5932         r_fb.water.numwaterplanes = 0;
5933 }
5934
5935 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5936 {
5937         int planeindex, bestplaneindex, vertexindex;
5938         vec3_t mins, maxs, normal, center, v, n;
5939         vec_t planescore, bestplanescore;
5940         mplane_t plane;
5941         r_waterstate_waterplane_t *p;
5942         texture_t *t = R_GetCurrentTexture(surface->texture);
5943
5944         rsurface.texture = t;
5945         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5946         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5947         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5948                 return;
5949         // average the vertex normals, find the surface bounds (after deformvertexes)
5950         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5951         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5952         VectorCopy(n, normal);
5953         VectorCopy(v, mins);
5954         VectorCopy(v, maxs);
5955         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5956         {
5957                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5958                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5959                 VectorAdd(normal, n, normal);
5960                 mins[0] = min(mins[0], v[0]);
5961                 mins[1] = min(mins[1], v[1]);
5962                 mins[2] = min(mins[2], v[2]);
5963                 maxs[0] = max(maxs[0], v[0]);
5964                 maxs[1] = max(maxs[1], v[1]);
5965                 maxs[2] = max(maxs[2], v[2]);
5966         }
5967         VectorNormalize(normal);
5968         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5969
5970         VectorCopy(normal, plane.normal);
5971         VectorNormalize(plane.normal);
5972         plane.dist = DotProduct(center, plane.normal);
5973         PlaneClassify(&plane);
5974         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5975         {
5976                 // skip backfaces (except if nocullface is set)
5977 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5978 //                      return;
5979                 VectorNegate(plane.normal, plane.normal);
5980                 plane.dist *= -1;
5981                 PlaneClassify(&plane);
5982         }
5983
5984
5985         // find a matching plane if there is one
5986         bestplaneindex = -1;
5987         bestplanescore = 1048576.0f;
5988         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5989         {
5990                 if(p->camera_entity == t->camera_entity)
5991                 {
5992                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5993                         if (bestplaneindex < 0 || bestplanescore > planescore)
5994                         {
5995                                 bestplaneindex = planeindex;
5996                                 bestplanescore = planescore;
5997                         }
5998                 }
5999         }
6000         planeindex = bestplaneindex;
6001         p = r_fb.water.waterplanes + planeindex;
6002
6003         // if this surface does not fit any known plane rendered this frame, add one
6004         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6005         {
6006                 // store the new plane
6007                 planeindex = r_fb.water.numwaterplanes++;
6008                 p = r_fb.water.waterplanes + planeindex;
6009                 p->plane = plane;
6010                 // clear materialflags and pvs
6011                 p->materialflags = 0;
6012                 p->pvsvalid = false;
6013                 p->camera_entity = t->camera_entity;
6014                 VectorCopy(mins, p->mins);
6015                 VectorCopy(maxs, p->maxs);
6016         }
6017         else
6018         {
6019                 // merge mins/maxs when we're adding this surface to the plane
6020                 p->mins[0] = min(p->mins[0], mins[0]);
6021                 p->mins[1] = min(p->mins[1], mins[1]);
6022                 p->mins[2] = min(p->mins[2], mins[2]);
6023                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6024                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6025                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6026         }
6027         // merge this surface's materialflags into the waterplane
6028         p->materialflags |= t->currentmaterialflags;
6029         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6030         {
6031                 // merge this surface's PVS into the waterplane
6032                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6033                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6034                 {
6035                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6036                         p->pvsvalid = true;
6037                 }
6038         }
6039 }
6040
6041 extern cvar_t r_drawparticles;
6042 extern cvar_t r_drawdecals;
6043
6044 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6045 {
6046         int myscissor[4];
6047         r_refdef_view_t originalview;
6048         r_refdef_view_t myview;
6049         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;
6050         r_waterstate_waterplane_t *p;
6051         vec3_t visorigin;
6052         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;
6053         char vabuf[1024];
6054
6055         originalview = r_refdef.view;
6056
6057         // lowquality hack, temporarily shut down some cvars and restore afterwards
6058         qualityreduction = r_water_lowquality.integer;
6059         if (qualityreduction > 0)
6060         {
6061                 if (qualityreduction >= 1)
6062                 {
6063                         old_r_shadows = r_shadows.integer;
6064                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6065                         old_r_dlight = r_shadow_realtime_dlight.integer;
6066                         Cvar_SetValueQuick(&r_shadows, 0);
6067                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6068                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6069                 }
6070                 if (qualityreduction >= 2)
6071                 {
6072                         old_r_dynamic = r_dynamic.integer;
6073                         old_r_particles = r_drawparticles.integer;
6074                         old_r_decals = r_drawdecals.integer;
6075                         Cvar_SetValueQuick(&r_dynamic, 0);
6076                         Cvar_SetValueQuick(&r_drawparticles, 0);
6077                         Cvar_SetValueQuick(&r_drawdecals, 0);
6078                 }
6079         }
6080
6081         // make sure enough textures are allocated
6082         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6083         {
6084                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6085                 {
6086                         if (!p->texture_refraction)
6087                                 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);
6088                         if (!p->texture_refraction)
6089                                 goto error;
6090                         if (usewaterfbo)
6091                         {
6092                                 if (r_fb.water.depthtexture == NULL)
6093                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6094                                 if (p->fbo_refraction == 0)
6095                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6096                         }
6097                 }
6098                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6099                 {
6100                         if (!p->texture_camera)
6101                                 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);
6102                         if (!p->texture_camera)
6103                                 goto error;
6104                         if (usewaterfbo)
6105                         {
6106                                 if (r_fb.water.depthtexture == NULL)
6107                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6108                                 if (p->fbo_camera == 0)
6109                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6110                         }
6111                 }
6112
6113                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6114                 {
6115                         if (!p->texture_reflection)
6116                                 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);
6117                         if (!p->texture_reflection)
6118                                 goto error;
6119                         if (usewaterfbo)
6120                         {
6121                                 if (r_fb.water.depthtexture == NULL)
6122                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6123                                 if (p->fbo_reflection == 0)
6124                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6125                         }
6126                 }
6127         }
6128
6129         // render views
6130         r_refdef.view = originalview;
6131         r_refdef.view.showdebug = false;
6132         r_refdef.view.width = r_fb.water.waterwidth;
6133         r_refdef.view.height = r_fb.water.waterheight;
6134         r_refdef.view.useclipplane = true;
6135         myview = r_refdef.view;
6136         r_fb.water.renderingscene = true;
6137         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6138         {
6139                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6140                 {
6141                         r_refdef.view = myview;
6142                         if(r_water_scissormode.integer)
6143                         {
6144                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6145                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6146                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6147                         }
6148
6149                         // render reflected scene and copy into texture
6150                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6151                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6152                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6153                         r_refdef.view.clipplane = p->plane;
6154                         // reverse the cullface settings for this render
6155                         r_refdef.view.cullface_front = GL_FRONT;
6156                         r_refdef.view.cullface_back = GL_BACK;
6157                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6158                         {
6159                                 r_refdef.view.usecustompvs = true;
6160                                 if (p->pvsvalid)
6161                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6162                                 else
6163                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6164                         }
6165
6166                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6167                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6168                         R_ClearScreen(r_refdef.fogenabled);
6169                         if(r_water_scissormode.integer & 2)
6170                                 R_View_UpdateWithScissor(myscissor);
6171                         else
6172                                 R_View_Update();
6173                         R_AnimCache_CacheVisibleEntities();
6174                         if(r_water_scissormode.integer & 1)
6175                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6176                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6177
6178                         if (!p->fbo_reflection)
6179                                 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);
6180                         r_fb.water.hideplayer = false;
6181                 }
6182
6183                 // render the normal view scene and copy into texture
6184                 // (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)
6185                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6186                 {
6187                         r_refdef.view = myview;
6188                         if(r_water_scissormode.integer)
6189                         {
6190                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6191                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6192                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6193                         }
6194
6195                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6196
6197                         r_refdef.view.clipplane = p->plane;
6198                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6199                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6200
6201                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6202                         {
6203                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6204                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6205                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6206                                 R_RenderView_UpdateViewVectors();
6207                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6208                                 {
6209                                         r_refdef.view.usecustompvs = true;
6210                                         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);
6211                                 }
6212                         }
6213
6214                         PlaneClassify(&r_refdef.view.clipplane);
6215
6216                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6217                         R_ClearScreen(r_refdef.fogenabled);
6218                         if(r_water_scissormode.integer & 2)
6219                                 R_View_UpdateWithScissor(myscissor);
6220                         else
6221                                 R_View_Update();
6222                         R_AnimCache_CacheVisibleEntities();
6223                         if(r_water_scissormode.integer & 1)
6224                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6225                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6226
6227                         if (!p->fbo_refraction)
6228                                 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);
6229                         r_fb.water.hideplayer = false;
6230                 }
6231                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6232                 {
6233                         r_refdef.view = myview;
6234
6235                         r_refdef.view.clipplane = p->plane;
6236                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6237                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6238
6239                         r_refdef.view.width = r_fb.water.camerawidth;
6240                         r_refdef.view.height = r_fb.water.cameraheight;
6241                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6242                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6243                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6244                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6245
6246                         if(p->camera_entity)
6247                         {
6248                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6249                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6250                         }
6251
6252                         // note: all of the view is used for displaying... so
6253                         // there is no use in scissoring
6254
6255                         // reverse the cullface settings for this render
6256                         r_refdef.view.cullface_front = GL_FRONT;
6257                         r_refdef.view.cullface_back = GL_BACK;
6258                         // also reverse the view matrix
6259                         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
6260                         R_RenderView_UpdateViewVectors();
6261                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6262                         {
6263                                 r_refdef.view.usecustompvs = true;
6264                                 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);
6265                         }
6266                         
6267                         // camera needs no clipplane
6268                         r_refdef.view.useclipplane = false;
6269
6270                         PlaneClassify(&r_refdef.view.clipplane);
6271
6272                         r_fb.water.hideplayer = false;
6273
6274                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6275                         R_ClearScreen(r_refdef.fogenabled);
6276                         R_View_Update();
6277                         R_AnimCache_CacheVisibleEntities();
6278                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6279
6280                         if (!p->fbo_camera)
6281                                 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);
6282                         r_fb.water.hideplayer = false;
6283                 }
6284
6285         }
6286         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6287         r_fb.water.renderingscene = false;
6288         r_refdef.view = originalview;
6289         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6290         if (!r_fb.water.depthtexture)
6291                 R_ClearScreen(r_refdef.fogenabled);
6292         R_View_Update();
6293         R_AnimCache_CacheVisibleEntities();
6294         goto finish;
6295 error:
6296         r_refdef.view = originalview;
6297         r_fb.water.renderingscene = false;
6298         Cvar_SetValueQuick(&r_water, 0);
6299         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6300 finish:
6301         // lowquality hack, restore cvars
6302         if (qualityreduction > 0)
6303         {
6304                 if (qualityreduction >= 1)
6305                 {
6306                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6307                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6308                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6309                 }
6310                 if (qualityreduction >= 2)
6311                 {
6312                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6313                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6314                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6315                 }
6316         }
6317 }
6318
6319 static void R_Bloom_StartFrame(void)
6320 {
6321         int i;
6322         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6323         int viewwidth, viewheight;
6324         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6325         textype_t textype = TEXTYPE_COLORBUFFER;
6326
6327         switch (vid.renderpath)
6328         {
6329         case RENDERPATH_GL20:
6330                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6331                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6332                 {
6333                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6334                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6335                 }
6336                 break;
6337         case RENDERPATH_GL11:
6338         case RENDERPATH_GL13:
6339         case RENDERPATH_GLES1:
6340         case RENDERPATH_GLES2:
6341         case RENDERPATH_D3D9:
6342         case RENDERPATH_D3D10:
6343         case RENDERPATH_D3D11:
6344                 r_fb.usedepthtextures = false;
6345                 break;
6346         case RENDERPATH_SOFT:
6347                 r_fb.usedepthtextures = true;
6348                 break;
6349         }
6350
6351         if (r_viewscale_fpsscaling.integer)
6352         {
6353                 double actualframetime;
6354                 double targetframetime;
6355                 double adjust;
6356                 actualframetime = r_refdef.lastdrawscreentime;
6357                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6358                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6359                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6360                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6361                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6362                 viewscalefpsadjusted += adjust;
6363                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6364         }
6365         else
6366                 viewscalefpsadjusted = 1.0f;
6367
6368         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6369
6370         switch(vid.renderpath)
6371         {
6372         case RENDERPATH_GL20:
6373         case RENDERPATH_D3D9:
6374         case RENDERPATH_D3D10:
6375         case RENDERPATH_D3D11:
6376         case RENDERPATH_SOFT:
6377         case RENDERPATH_GLES2:
6378                 break;
6379         case RENDERPATH_GL11:
6380         case RENDERPATH_GL13:
6381         case RENDERPATH_GLES1:
6382                 return;
6383         }
6384
6385         // set bloomwidth and bloomheight to the bloom resolution that will be
6386         // used (often less than the screen resolution for faster rendering)
6387         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6388         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6389         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6390         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6391         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6392
6393         // calculate desired texture sizes
6394         if (vid.support.arb_texture_non_power_of_two)
6395         {
6396                 screentexturewidth = vid.width;
6397                 screentextureheight = vid.height;
6398                 bloomtexturewidth = r_fb.bloomwidth;
6399                 bloomtextureheight = r_fb.bloomheight;
6400         }
6401         else
6402         {
6403                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6404                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6405                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6406                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6407         }
6408
6409         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))
6410         {
6411                 Cvar_SetValueQuick(&r_bloom, 0);
6412                 Cvar_SetValueQuick(&r_motionblur, 0);
6413                 Cvar_SetValueQuick(&r_damageblur, 0);
6414         }
6415
6416         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6417          && !r_bloom.integer
6418          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6419          && !useviewfbo
6420          && r_viewscale.value == 1.0f
6421          && !r_viewscale_fpsscaling.integer)
6422                 screentexturewidth = screentextureheight = 0;
6423         if (!r_bloom.integer)
6424                 bloomtexturewidth = bloomtextureheight = 0;
6425
6426         // allocate textures as needed
6427         if (r_fb.screentexturewidth != screentexturewidth
6428          || r_fb.screentextureheight != screentextureheight
6429          || r_fb.bloomtexturewidth != bloomtexturewidth
6430          || r_fb.bloomtextureheight != bloomtextureheight
6431          || r_fb.textype != textype
6432          || useviewfbo != (r_fb.fbo != 0))
6433         {
6434                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6435                 {
6436                         if (r_fb.bloomtexture[i])
6437                                 R_FreeTexture(r_fb.bloomtexture[i]);
6438                         r_fb.bloomtexture[i] = NULL;
6439
6440                         if (r_fb.bloomfbo[i])
6441                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6442                         r_fb.bloomfbo[i] = 0;
6443                 }
6444
6445                 if (r_fb.fbo)
6446                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6447                 r_fb.fbo = 0;
6448
6449                 if (r_fb.colortexture)
6450                         R_FreeTexture(r_fb.colortexture);
6451                 r_fb.colortexture = NULL;
6452
6453                 if (r_fb.depthtexture)
6454                         R_FreeTexture(r_fb.depthtexture);
6455                 r_fb.depthtexture = NULL;
6456
6457                 if (r_fb.ghosttexture)
6458                         R_FreeTexture(r_fb.ghosttexture);
6459                 r_fb.ghosttexture = NULL;
6460
6461                 r_fb.screentexturewidth = screentexturewidth;
6462                 r_fb.screentextureheight = screentextureheight;
6463                 r_fb.bloomtexturewidth = bloomtexturewidth;
6464                 r_fb.bloomtextureheight = bloomtextureheight;
6465                 r_fb.textype = textype;
6466
6467                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6468                 {
6469                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6470                                 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);
6471                         r_fb.ghosttexture_valid = false;
6472                         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);
6473                         if (useviewfbo)
6474                         {
6475                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6476                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6477                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6478                         }
6479                 }
6480
6481                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6482                 {
6483                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6484                         {
6485                                 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);
6486                                 if (useviewfbo)
6487                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6488                         }
6489                 }
6490         }
6491
6492         // bloom texture is a different resolution
6493         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6494         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6495         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6496         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6497         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6498
6499         // set up a texcoord array for the full resolution screen image
6500         // (we have to keep this around to copy back during final render)
6501         r_fb.screentexcoord2f[0] = 0;
6502         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6503         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6504         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6505         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6506         r_fb.screentexcoord2f[5] = 0;
6507         r_fb.screentexcoord2f[6] = 0;
6508         r_fb.screentexcoord2f[7] = 0;
6509
6510         if(r_fb.fbo) 
6511         {
6512                 for (i = 1;i < 8;i += 2)
6513                 {
6514                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6515                 }
6516         }
6517
6518         // set up a texcoord array for the reduced resolution bloom image
6519         // (which will be additive blended over the screen image)
6520         r_fb.bloomtexcoord2f[0] = 0;
6521         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6522         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6523         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6524         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6525         r_fb.bloomtexcoord2f[5] = 0;
6526         r_fb.bloomtexcoord2f[6] = 0;
6527         r_fb.bloomtexcoord2f[7] = 0;
6528
6529         switch(vid.renderpath)
6530         {
6531         case RENDERPATH_GL11:
6532         case RENDERPATH_GL13:
6533         case RENDERPATH_GL20:
6534         case RENDERPATH_SOFT:
6535         case RENDERPATH_GLES1:
6536         case RENDERPATH_GLES2:
6537                 break;
6538         case RENDERPATH_D3D9:
6539         case RENDERPATH_D3D10:
6540         case RENDERPATH_D3D11:
6541                 for (i = 0;i < 4;i++)
6542                 {
6543                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6544                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6545                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6546                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6547                 }
6548                 break;
6549         }
6550
6551         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6552
6553         if (r_fb.fbo)
6554                 r_refdef.view.clear = true;
6555 }
6556
6557 static void R_Bloom_MakeTexture(void)
6558 {
6559         int x, range, dir;
6560         float xoffset, yoffset, r, brighten;
6561         rtexture_t *intex;
6562         float colorscale = r_bloom_colorscale.value;
6563
6564         r_refdef.stats[r_stat_bloom]++;
6565     
6566 #if 0
6567     // this copy is unnecessary since it happens in R_BlendView already
6568         if (!r_fb.fbo)
6569         {
6570                 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);
6571                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6572         }
6573 #endif
6574
6575         // scale down screen texture to the bloom texture size
6576         CHECKGLERROR
6577         r_fb.bloomindex = 0;
6578         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6579         R_SetViewport(&r_fb.bloomviewport);
6580         GL_DepthTest(false);
6581         GL_BlendFunc(GL_ONE, GL_ZERO);
6582         GL_Color(colorscale, colorscale, colorscale, 1);
6583         // 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...
6584         switch(vid.renderpath)
6585         {
6586         case RENDERPATH_GL11:
6587         case RENDERPATH_GL13:
6588         case RENDERPATH_GL20:
6589         case RENDERPATH_GLES1:
6590         case RENDERPATH_GLES2:
6591         case RENDERPATH_SOFT:
6592                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6593                 break;
6594         case RENDERPATH_D3D9:
6595         case RENDERPATH_D3D10:
6596         case RENDERPATH_D3D11:
6597                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6598                 break;
6599         }
6600         // TODO: do boxfilter scale-down in shader?
6601         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6602         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6603         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6604
6605         // we now have a properly scaled bloom image
6606         if (!r_fb.bloomfbo[r_fb.bloomindex])
6607         {
6608                 // copy it into the bloom texture
6609                 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);
6610                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6611         }
6612
6613         // multiply bloom image by itself as many times as desired
6614         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6615         {
6616                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6617                 r_fb.bloomindex ^= 1;
6618                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6619                 x *= 2;
6620                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6621                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6622                 {
6623                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6624                         GL_Color(r,r,r,1); // apply fix factor
6625                 }
6626                 else
6627                 {
6628                         if(x <= 2)
6629                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6630                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6631                         GL_Color(1,1,1,1); // no fix factor supported here
6632                 }
6633                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6634                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6635                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6636                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6637
6638                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6639                 {
6640                         // copy the darkened image to a texture
6641                         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);
6642                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6643                 }
6644         }
6645
6646         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6647         brighten = r_bloom_brighten.value;
6648         brighten = sqrt(brighten);
6649         if(range >= 1)
6650                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6651
6652         for (dir = 0;dir < 2;dir++)
6653         {
6654                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6655                 r_fb.bloomindex ^= 1;
6656                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6657                 // blend on at multiple vertical offsets to achieve a vertical blur
6658                 // TODO: do offset blends using GLSL
6659                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6660                 GL_BlendFunc(GL_ONE, GL_ZERO);
6661                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6662                 for (x = -range;x <= range;x++)
6663                 {
6664                         if (!dir){xoffset = 0;yoffset = x;}
6665                         else {xoffset = x;yoffset = 0;}
6666                         xoffset /= (float)r_fb.bloomtexturewidth;
6667                         yoffset /= (float)r_fb.bloomtextureheight;
6668                         // compute a texcoord array with the specified x and y offset
6669                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6670                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6671                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6672                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6673                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6674                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6675                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6676                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6677                         // this r value looks like a 'dot' particle, fading sharply to
6678                         // black at the edges
6679                         // (probably not realistic but looks good enough)
6680                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6681                         //r = brighten/(range*2+1);
6682                         r = brighten / (range * 2 + 1);
6683                         if(range >= 1)
6684                                 r *= (1 - x*x/(float)(range*range));
6685                         GL_Color(r, r, r, 1);
6686                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6687                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6688                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6689                         GL_BlendFunc(GL_ONE, GL_ONE);
6690                 }
6691
6692                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6693                 {
6694                         // copy the vertically or horizontally blurred bloom view to a texture
6695                         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);
6696                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6697                 }
6698         }
6699 }
6700
6701 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6702 {
6703         unsigned int permutation;
6704         float uservecs[4][4];
6705
6706         R_EntityMatrix(&identitymatrix);
6707
6708         switch (vid.renderpath)
6709         {
6710         case RENDERPATH_GL20:
6711         case RENDERPATH_D3D9:
6712         case RENDERPATH_D3D10:
6713         case RENDERPATH_D3D11:
6714         case RENDERPATH_SOFT:
6715         case RENDERPATH_GLES2:
6716                 permutation =
6717                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6718                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6719                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6720                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6721                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6722
6723                 if (r_fb.colortexture)
6724                 {
6725                         if (!r_fb.fbo)
6726                         {
6727                                 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);
6728                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6729                         }
6730
6731                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6732                         {
6733                                 // declare variables
6734                                 float blur_factor, blur_mouseaccel, blur_velocity;
6735                                 static float blur_average; 
6736                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6737
6738                                 // set a goal for the factoring
6739                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6740                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6741                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6742                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6743                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6744                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6745
6746                                 // from the goal, pick an averaged value between goal and last value
6747                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6748                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6749
6750                                 // enforce minimum amount of blur 
6751                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6752
6753                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6754
6755                                 // calculate values into a standard alpha
6756                                 cl.motionbluralpha = 1 - exp(-
6757                                                 (
6758                                                  (r_motionblur.value * blur_factor / 80)
6759                                                  +
6760                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6761                                                 )
6762                                                 /
6763                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6764                                           );
6765
6766                                 // randomization for the blur value to combat persistent ghosting
6767                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6768                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6769
6770                                 // apply the blur
6771                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6772                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6773                                 {
6774                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6775                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6776                                         switch(vid.renderpath)
6777                                         {
6778                                         case RENDERPATH_GL11:
6779                                         case RENDERPATH_GL13:
6780                                         case RENDERPATH_GL20:
6781                                         case RENDERPATH_GLES1:
6782                                         case RENDERPATH_GLES2:
6783                                         case RENDERPATH_SOFT:
6784                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6785                                                 break;
6786                                         case RENDERPATH_D3D9:
6787                                         case RENDERPATH_D3D10:
6788                                         case RENDERPATH_D3D11:
6789                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6790                                                 break;
6791                                         }
6792                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6793                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6794                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6795                                 }
6796
6797                                 // updates old view angles for next pass
6798                                 VectorCopy(cl.viewangles, blur_oldangles);
6799
6800                                 // copy view into the ghost texture
6801                                 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);
6802                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6803                                 r_fb.ghosttexture_valid = true;
6804                         }
6805                 }
6806                 else
6807                 {
6808                         // no r_fb.colortexture means we're rendering to the real fb
6809                         // we may still have to do view tint...
6810                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6811                         {
6812                                 // apply a color tint to the whole view
6813                                 R_ResetViewRendering2D(0, NULL, NULL);
6814                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6815                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6816                                 R_SetupShader_Generic_NoTexture(false, true);
6817                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6818                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6819                         }
6820                         break; // no screen processing, no bloom, skip it
6821                 }
6822
6823                 if (r_fb.bloomtexture[0])
6824                 {
6825                         // make the bloom texture
6826                         R_Bloom_MakeTexture();
6827                 }
6828
6829 #if _MSC_VER >= 1400
6830 #define sscanf sscanf_s
6831 #endif
6832                 memset(uservecs, 0, sizeof(uservecs));
6833                 if (r_glsl_postprocess_uservec1_enable.integer)
6834                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6835                 if (r_glsl_postprocess_uservec2_enable.integer)
6836                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6837                 if (r_glsl_postprocess_uservec3_enable.integer)
6838                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6839                 if (r_glsl_postprocess_uservec4_enable.integer)
6840                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6841
6842                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6843                 GL_Color(1, 1, 1, 1);
6844                 GL_BlendFunc(GL_ONE, GL_ZERO);
6845
6846                 switch(vid.renderpath)
6847                 {
6848                 case RENDERPATH_GL20:
6849                 case RENDERPATH_GLES2:
6850                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6851                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6852                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6853                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6854                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6855                         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]);
6856                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6857                         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]);
6858                         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]);
6859                         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]);
6860                         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]);
6861                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6862                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6863                         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);
6864                         break;
6865                 case RENDERPATH_D3D9:
6866 #ifdef SUPPORTD3D
6867                         // 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...
6868                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6869                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6870                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6871                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6872                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6873                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6874                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6875                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6876                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6877                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6878                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6879                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6880                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6881                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6882 #endif
6883                         break;
6884                 case RENDERPATH_D3D10:
6885                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6886                         break;
6887                 case RENDERPATH_D3D11:
6888                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6889                         break;
6890                 case RENDERPATH_SOFT:
6891                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6892                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6893                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6894                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6895                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6896                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6897                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6898                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6899                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6900                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6901                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6902                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6903                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6904                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6905                         break;
6906                 default:
6907                         break;
6908                 }
6909                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6910                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6911                 break;
6912         case RENDERPATH_GL11:
6913         case RENDERPATH_GL13:
6914         case RENDERPATH_GLES1:
6915                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6916                 {
6917                         // apply a color tint to the whole view
6918                         R_ResetViewRendering2D(0, NULL, NULL);
6919                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6920                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6921                         R_SetupShader_Generic_NoTexture(false, true);
6922                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6923                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6924                 }
6925                 break;
6926         }
6927 }
6928
6929 matrix4x4_t r_waterscrollmatrix;
6930
6931 void R_UpdateFog(void)
6932 {
6933         // Nehahra fog
6934         if (gamemode == GAME_NEHAHRA)
6935         {
6936                 if (gl_fogenable.integer)
6937                 {
6938                         r_refdef.oldgl_fogenable = true;
6939                         r_refdef.fog_density = gl_fogdensity.value;
6940                         r_refdef.fog_red = gl_fogred.value;
6941                         r_refdef.fog_green = gl_foggreen.value;
6942                         r_refdef.fog_blue = gl_fogblue.value;
6943                         r_refdef.fog_alpha = 1;
6944                         r_refdef.fog_start = 0;
6945                         r_refdef.fog_end = gl_skyclip.value;
6946                         r_refdef.fog_height = 1<<30;
6947                         r_refdef.fog_fadedepth = 128;
6948                 }
6949                 else if (r_refdef.oldgl_fogenable)
6950                 {
6951                         r_refdef.oldgl_fogenable = false;
6952                         r_refdef.fog_density = 0;
6953                         r_refdef.fog_red = 0;
6954                         r_refdef.fog_green = 0;
6955                         r_refdef.fog_blue = 0;
6956                         r_refdef.fog_alpha = 0;
6957                         r_refdef.fog_start = 0;
6958                         r_refdef.fog_end = 0;
6959                         r_refdef.fog_height = 1<<30;
6960                         r_refdef.fog_fadedepth = 128;
6961                 }
6962         }
6963
6964         // fog parms
6965         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6966         r_refdef.fog_start = max(0, r_refdef.fog_start);
6967         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6968
6969         if (r_refdef.fog_density && r_drawfog.integer)
6970         {
6971                 r_refdef.fogenabled = true;
6972                 // this is the point where the fog reaches 0.9986 alpha, which we
6973                 // consider a good enough cutoff point for the texture
6974                 // (0.9986 * 256 == 255.6)
6975                 if (r_fog_exp2.integer)
6976                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6977                 else
6978                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6979                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6980                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6981                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6982                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6983                         R_BuildFogHeightTexture();
6984                 // fog color was already set
6985                 // update the fog texture
6986                 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)
6987                         R_BuildFogTexture();
6988                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6989                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6990         }
6991         else
6992                 r_refdef.fogenabled = false;
6993
6994         // fog color
6995         if (r_refdef.fog_density)
6996         {
6997                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6998                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6999                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7000
7001                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7002                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7003                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7004                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7005
7006                 {
7007                         vec3_t fogvec;
7008                         VectorCopy(r_refdef.fogcolor, fogvec);
7009                         //   color.rgb *= ContrastBoost * SceneBrightness;
7010                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7011                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7012                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7013                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7014                 }
7015         }
7016 }
7017
7018 void R_UpdateVariables(void)
7019 {
7020         R_Textures_Frame();
7021
7022         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7023
7024         r_refdef.farclip = r_farclip_base.value;
7025         if (r_refdef.scene.worldmodel)
7026                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7027         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7028
7029         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7030                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7031         r_refdef.polygonfactor = 0;
7032         r_refdef.polygonoffset = 0;
7033         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7034         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7035
7036         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7037         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7038         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7039         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7040         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7041         if (FAKELIGHT_ENABLED)
7042         {
7043                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7044         }
7045         else if (r_refdef.scene.worldmodel)
7046         {
7047                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7048         }
7049         if (r_showsurfaces.integer)
7050         {
7051                 r_refdef.scene.rtworld = false;
7052                 r_refdef.scene.rtworldshadows = false;
7053                 r_refdef.scene.rtdlight = false;
7054                 r_refdef.scene.rtdlightshadows = false;
7055                 r_refdef.lightmapintensity = 0;
7056         }
7057
7058         r_gpuskeletal = false;
7059         switch(vid.renderpath)
7060         {
7061         case RENDERPATH_GL20:
7062                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7063         case RENDERPATH_D3D9:
7064         case RENDERPATH_D3D10:
7065         case RENDERPATH_D3D11:
7066         case RENDERPATH_SOFT:
7067         case RENDERPATH_GLES2:
7068                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7069                 {
7070                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7071                         {
7072                                 // build GLSL gamma texture
7073 #define RAMPWIDTH 256
7074                                 unsigned short ramp[RAMPWIDTH * 3];
7075                                 unsigned char rampbgr[RAMPWIDTH][4];
7076                                 int i;
7077
7078                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7079
7080                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7081                                 for(i = 0; i < RAMPWIDTH; ++i)
7082                                 {
7083                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7084                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7085                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7086                                         rampbgr[i][3] = 0;
7087                                 }
7088                                 if (r_texture_gammaramps)
7089                                 {
7090                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7091                                 }
7092                                 else
7093                                 {
7094                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7095                                 }
7096                         }
7097                 }
7098                 else
7099                 {
7100                         // remove GLSL gamma texture
7101                 }
7102                 break;
7103         case RENDERPATH_GL11:
7104         case RENDERPATH_GL13:
7105         case RENDERPATH_GLES1:
7106                 break;
7107         }
7108 }
7109
7110 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7111 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7112 /*
7113 ================
7114 R_SelectScene
7115 ================
7116 */
7117 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7118         if( scenetype != r_currentscenetype ) {
7119                 // store the old scenetype
7120                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7121                 r_currentscenetype = scenetype;
7122                 // move in the new scene
7123                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7124         }
7125 }
7126
7127 /*
7128 ================
7129 R_GetScenePointer
7130 ================
7131 */
7132 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7133 {
7134         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7135         if( scenetype == r_currentscenetype ) {
7136                 return &r_refdef.scene;
7137         } else {
7138                 return &r_scenes_store[ scenetype ];
7139         }
7140 }
7141
7142 static int R_SortEntities_Compare(const void *ap, const void *bp)
7143 {
7144         const entity_render_t *a = *(const entity_render_t **)ap;
7145         const entity_render_t *b = *(const entity_render_t **)bp;
7146
7147         // 1. compare model
7148         if(a->model < b->model)
7149                 return -1;
7150         if(a->model > b->model)
7151                 return +1;
7152
7153         // 2. compare skin
7154         // TODO possibly calculate the REAL skinnum here first using
7155         // skinscenes?
7156         if(a->skinnum < b->skinnum)
7157                 return -1;
7158         if(a->skinnum > b->skinnum)
7159                 return +1;
7160
7161         // everything we compared is equal
7162         return 0;
7163 }
7164 static void R_SortEntities(void)
7165 {
7166         // below or equal 2 ents, sorting never gains anything
7167         if(r_refdef.scene.numentities <= 2)
7168                 return;
7169         // sort
7170         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7171 }
7172
7173 /*
7174 ================
7175 R_RenderView
7176 ================
7177 */
7178 int dpsoftrast_test;
7179 extern cvar_t r_shadow_bouncegrid;
7180 void R_RenderView(void)
7181 {
7182         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7183         int fbo;
7184         rtexture_t *depthtexture;
7185         rtexture_t *colortexture;
7186
7187         dpsoftrast_test = r_test.integer;
7188
7189         if (r_timereport_active)
7190                 R_TimeReport("start");
7191         r_textureframe++; // used only by R_GetCurrentTexture
7192         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7193
7194         if(R_CompileShader_CheckStaticParms())
7195                 R_GLSL_Restart_f();
7196
7197         if (!r_drawentities.integer)
7198                 r_refdef.scene.numentities = 0;
7199         else if (r_sortentities.integer)
7200                 R_SortEntities();
7201
7202         R_AnimCache_ClearCache();
7203
7204         /* adjust for stereo display */
7205         if(R_Stereo_Active())
7206         {
7207                 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);
7208                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7209         }
7210
7211         if (r_refdef.view.isoverlay)
7212         {
7213                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7214                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7215                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7216                 R_TimeReport("depthclear");
7217
7218                 r_refdef.view.showdebug = false;
7219
7220                 r_fb.water.enabled = false;
7221                 r_fb.water.numwaterplanes = 0;
7222
7223                 R_RenderScene(0, NULL, NULL);
7224
7225                 r_refdef.view.matrix = originalmatrix;
7226
7227                 CHECKGLERROR
7228                 return;
7229         }
7230
7231         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7232         {
7233                 r_refdef.view.matrix = originalmatrix;
7234                 return;
7235         }
7236
7237         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7238
7239         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7240                 // in sRGB fallback, behave similar to true sRGB: convert this
7241                 // value from linear to sRGB
7242                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7243
7244         R_RenderView_UpdateViewVectors();
7245
7246         R_Shadow_UpdateWorldLightSelection();
7247
7248         R_Bloom_StartFrame();
7249
7250         // apply bloom brightness offset
7251         if(r_fb.bloomtexture[0])
7252                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7253
7254         R_Water_StartFrame();
7255
7256         // now we probably have an fbo to render into
7257         fbo = r_fb.fbo;
7258         depthtexture = r_fb.depthtexture;
7259         colortexture = r_fb.colortexture;
7260
7261         CHECKGLERROR
7262         if (r_timereport_active)
7263                 R_TimeReport("viewsetup");
7264
7265         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7266
7267         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7268         {
7269                 R_ClearScreen(r_refdef.fogenabled);
7270                 if (r_timereport_active)
7271                         R_TimeReport("viewclear");
7272         }
7273         r_refdef.view.clear = true;
7274
7275         r_refdef.view.showdebug = true;
7276
7277         R_View_Update();
7278         if (r_timereport_active)
7279                 R_TimeReport("visibility");
7280
7281         R_AnimCache_CacheVisibleEntities();
7282         if (r_timereport_active)
7283                 R_TimeReport("animcache");
7284
7285         R_Shadow_UpdateBounceGridTexture();
7286         if (r_timereport_active && r_shadow_bouncegrid.integer)
7287                 R_TimeReport("bouncegrid");
7288
7289         r_fb.water.numwaterplanes = 0;
7290         if (r_fb.water.enabled)
7291                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7292
7293         R_RenderScene(fbo, depthtexture, colortexture);
7294         r_fb.water.numwaterplanes = 0;
7295
7296         R_BlendView(fbo, depthtexture, colortexture);
7297         if (r_timereport_active)
7298                 R_TimeReport("blendview");
7299
7300         GL_Scissor(0, 0, vid.width, vid.height);
7301         GL_ScissorTest(false);
7302
7303         r_refdef.view.matrix = originalmatrix;
7304
7305         CHECKGLERROR
7306 }
7307
7308 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7309 {
7310         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7311         {
7312                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7313                 if (r_timereport_active)
7314                         R_TimeReport("waterworld");
7315         }
7316
7317         // don't let sound skip if going slow
7318         if (r_refdef.scene.extraupdate)
7319                 S_ExtraUpdate ();
7320
7321         R_DrawModelsAddWaterPlanes();
7322         if (r_timereport_active)
7323                 R_TimeReport("watermodels");
7324
7325         if (r_fb.water.numwaterplanes)
7326         {
7327                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7328                 if (r_timereport_active)
7329                         R_TimeReport("waterscenes");
7330         }
7331 }
7332
7333 extern cvar_t cl_locs_show;
7334 static void R_DrawLocs(void);
7335 static void R_DrawEntityBBoxes(void);
7336 static void R_DrawModelDecals(void);
7337 extern cvar_t cl_decals_newsystem;
7338 extern qboolean r_shadow_usingdeferredprepass;
7339 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7340 {
7341         qboolean shadowmapping = false;
7342
7343         if (r_timereport_active)
7344                 R_TimeReport("beginscene");
7345
7346         r_refdef.stats[r_stat_renders]++;
7347
7348         R_UpdateFog();
7349
7350         // don't let sound skip if going slow
7351         if (r_refdef.scene.extraupdate)
7352                 S_ExtraUpdate ();
7353
7354         R_MeshQueue_BeginScene();
7355
7356         R_SkyStartFrame();
7357
7358         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);
7359
7360         if (r_timereport_active)
7361                 R_TimeReport("skystartframe");
7362
7363         if (cl.csqc_vidvars.drawworld)
7364         {
7365                 // don't let sound skip if going slow
7366                 if (r_refdef.scene.extraupdate)
7367                         S_ExtraUpdate ();
7368
7369                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7370                 {
7371                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7372                         if (r_timereport_active)
7373                                 R_TimeReport("worldsky");
7374                 }
7375
7376                 if (R_DrawBrushModelsSky() && r_timereport_active)
7377                         R_TimeReport("bmodelsky");
7378
7379                 if (skyrendermasked && skyrenderlater)
7380                 {
7381                         // we have to force off the water clipping plane while rendering sky
7382                         R_SetupView(false, fbo, depthtexture, colortexture);
7383                         R_Sky();
7384                         R_SetupView(true, fbo, depthtexture, colortexture);
7385                         if (r_timereport_active)
7386                                 R_TimeReport("sky");
7387                 }
7388         }
7389
7390         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7391         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7392                 R_Shadow_PrepareModelShadows();
7393         if (r_timereport_active)
7394                 R_TimeReport("preparelights");
7395
7396         if (R_Shadow_ShadowMappingEnabled())
7397                 shadowmapping = true;
7398
7399         if (r_shadow_usingdeferredprepass)
7400                 R_Shadow_DrawPrepass();
7401
7402         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7403         {
7404                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7405                 if (r_timereport_active)
7406                         R_TimeReport("worlddepth");
7407         }
7408         if (r_depthfirst.integer >= 2)
7409         {
7410                 R_DrawModelsDepth();
7411                 if (r_timereport_active)
7412                         R_TimeReport("modeldepth");
7413         }
7414
7415         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7416         {
7417                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7418                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7419                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7420                 // don't let sound skip if going slow
7421                 if (r_refdef.scene.extraupdate)
7422                         S_ExtraUpdate ();
7423         }
7424
7425         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7426         {
7427                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7428                 if (r_timereport_active)
7429                         R_TimeReport("world");
7430         }
7431
7432         // don't let sound skip if going slow
7433         if (r_refdef.scene.extraupdate)
7434                 S_ExtraUpdate ();
7435
7436         R_DrawModels();
7437         if (r_timereport_active)
7438                 R_TimeReport("models");
7439
7440         // don't let sound skip if going slow
7441         if (r_refdef.scene.extraupdate)
7442                 S_ExtraUpdate ();
7443
7444         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7445         {
7446                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7447                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7448                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7449                 // don't let sound skip if going slow
7450                 if (r_refdef.scene.extraupdate)
7451                         S_ExtraUpdate ();
7452         }
7453
7454         if (!r_shadow_usingdeferredprepass)
7455         {
7456                 R_Shadow_DrawLights();
7457                 if (r_timereport_active)
7458                         R_TimeReport("rtlights");
7459         }
7460
7461         // don't let sound skip if going slow
7462         if (r_refdef.scene.extraupdate)
7463                 S_ExtraUpdate ();
7464
7465         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7466         {
7467                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7468                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7469                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7470                 // don't let sound skip if going slow
7471                 if (r_refdef.scene.extraupdate)
7472                         S_ExtraUpdate ();
7473         }
7474
7475         if (cl.csqc_vidvars.drawworld)
7476         {
7477                 if (cl_decals_newsystem.integer)
7478                 {
7479                         R_DrawModelDecals();
7480                         if (r_timereport_active)
7481                                 R_TimeReport("modeldecals");
7482                 }
7483                 else
7484                 {
7485                         R_DrawDecals();
7486                         if (r_timereport_active)
7487                                 R_TimeReport("decals");
7488                 }
7489
7490                 R_DrawParticles();
7491                 if (r_timereport_active)
7492                         R_TimeReport("particles");
7493
7494                 R_DrawExplosions();
7495                 if (r_timereport_active)
7496                         R_TimeReport("explosions");
7497
7498                 R_DrawLightningBeams();
7499                 if (r_timereport_active)
7500                         R_TimeReport("lightning");
7501         }
7502
7503         if (cl.csqc_loaded)
7504                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7505
7506         if (r_refdef.view.showdebug)
7507         {
7508                 if (cl_locs_show.integer)
7509                 {
7510                         R_DrawLocs();
7511                         if (r_timereport_active)
7512                                 R_TimeReport("showlocs");
7513                 }
7514
7515                 if (r_drawportals.integer)
7516                 {
7517                         R_DrawPortals();
7518                         if (r_timereport_active)
7519                                 R_TimeReport("portals");
7520                 }
7521
7522                 if (r_showbboxes.value > 0)
7523                 {
7524                         R_DrawEntityBBoxes();
7525                         if (r_timereport_active)
7526                                 R_TimeReport("bboxes");
7527                 }
7528         }
7529
7530         if (r_transparent.integer)
7531         {
7532                 R_MeshQueue_RenderTransparent();
7533                 if (r_timereport_active)
7534                         R_TimeReport("drawtrans");
7535         }
7536
7537         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))
7538         {
7539                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7540                 if (r_timereport_active)
7541                         R_TimeReport("worlddebug");
7542                 R_DrawModelsDebug();
7543                 if (r_timereport_active)
7544                         R_TimeReport("modeldebug");
7545         }
7546
7547         if (cl.csqc_vidvars.drawworld)
7548         {
7549                 R_Shadow_DrawCoronas();
7550                 if (r_timereport_active)
7551                         R_TimeReport("coronas");
7552         }
7553
7554 #if 0
7555         {
7556                 GL_DepthTest(false);
7557                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7558                 GL_Color(1, 1, 1, 1);
7559                 qglBegin(GL_POLYGON);
7560                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7561                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7562                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7563                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7564                 qglEnd();
7565                 qglBegin(GL_POLYGON);
7566                 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]);
7567                 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]);
7568                 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]);
7569                 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]);
7570                 qglEnd();
7571                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7572         }
7573 #endif
7574
7575         // don't let sound skip if going slow
7576         if (r_refdef.scene.extraupdate)
7577                 S_ExtraUpdate ();
7578 }
7579
7580 static const unsigned short bboxelements[36] =
7581 {
7582         5, 1, 3, 5, 3, 7,
7583         6, 2, 0, 6, 0, 4,
7584         7, 3, 2, 7, 2, 6,
7585         4, 0, 1, 4, 1, 5,
7586         4, 5, 7, 4, 7, 6,
7587         1, 0, 2, 1, 2, 3,
7588 };
7589
7590 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7591 {
7592         int i;
7593         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7594
7595         RSurf_ActiveWorldEntity();
7596
7597         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7598         GL_DepthMask(false);
7599         GL_DepthRange(0, 1);
7600         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7601 //      R_Mesh_ResetTextureState();
7602
7603         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7604         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7605         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7606         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7607         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7608         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7609         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7610         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7611         R_FillColors(color4f, 8, cr, cg, cb, ca);
7612         if (r_refdef.fogenabled)
7613         {
7614                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7615                 {
7616                         f1 = RSurf_FogVertex(v);
7617                         f2 = 1 - f1;
7618                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7619                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7620                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7621                 }
7622         }
7623         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7624         R_Mesh_ResetTextureState();
7625         R_SetupShader_Generic_NoTexture(false, false);
7626         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7627 }
7628
7629 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7630 {
7631         prvm_prog_t *prog = SVVM_prog;
7632         int i;
7633         float color[4];
7634         prvm_edict_t *edict;
7635
7636         // this function draws bounding boxes of server entities
7637         if (!sv.active)
7638                 return;
7639
7640         GL_CullFace(GL_NONE);
7641         R_SetupShader_Generic_NoTexture(false, false);
7642
7643         for (i = 0;i < numsurfaces;i++)
7644         {
7645                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7646                 switch ((int)PRVM_serveredictfloat(edict, solid))
7647                 {
7648                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7649                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7650                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7651                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7652                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7653                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7654                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7655                 }
7656                 color[3] *= r_showbboxes.value;
7657                 color[3] = bound(0, color[3], 1);
7658                 GL_DepthTest(!r_showdisabledepthtest.integer);
7659                 GL_CullFace(r_refdef.view.cullface_front);
7660                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7661         }
7662 }
7663
7664 static void R_DrawEntityBBoxes(void)
7665 {
7666         int i;
7667         prvm_edict_t *edict;
7668         vec3_t center;
7669         prvm_prog_t *prog = SVVM_prog;
7670
7671         // this function draws bounding boxes of server entities
7672         if (!sv.active)
7673                 return;
7674
7675         for (i = 0;i < prog->num_edicts;i++)
7676         {
7677                 edict = PRVM_EDICT_NUM(i);
7678                 if (edict->priv.server->free)
7679                         continue;
7680                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7681                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7682                         continue;
7683                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7684                         continue;
7685                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7686                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7687         }
7688 }
7689
7690 static const int nomodelelement3i[24] =
7691 {
7692         5, 2, 0,
7693         5, 1, 2,
7694         5, 0, 3,
7695         5, 3, 1,
7696         0, 2, 4,
7697         2, 1, 4,
7698         3, 0, 4,
7699         1, 3, 4
7700 };
7701
7702 static const unsigned short nomodelelement3s[24] =
7703 {
7704         5, 2, 0,
7705         5, 1, 2,
7706         5, 0, 3,
7707         5, 3, 1,
7708         0, 2, 4,
7709         2, 1, 4,
7710         3, 0, 4,
7711         1, 3, 4
7712 };
7713
7714 static const float nomodelvertex3f[6*3] =
7715 {
7716         -16,   0,   0,
7717          16,   0,   0,
7718           0, -16,   0,
7719           0,  16,   0,
7720           0,   0, -16,
7721           0,   0,  16
7722 };
7723
7724 static const float nomodelcolor4f[6*4] =
7725 {
7726         0.0f, 0.0f, 0.5f, 1.0f,
7727         0.0f, 0.0f, 0.5f, 1.0f,
7728         0.0f, 0.5f, 0.0f, 1.0f,
7729         0.0f, 0.5f, 0.0f, 1.0f,
7730         0.5f, 0.0f, 0.0f, 1.0f,
7731         0.5f, 0.0f, 0.0f, 1.0f
7732 };
7733
7734 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7735 {
7736         int i;
7737         float f1, f2, *c;
7738         float color4f[6*4];
7739
7740         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);
7741
7742         // this is only called once per entity so numsurfaces is always 1, and
7743         // surfacelist is always {0}, so this code does not handle batches
7744
7745         if (rsurface.ent_flags & RENDER_ADDITIVE)
7746         {
7747                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7748                 GL_DepthMask(false);
7749         }
7750         else if (rsurface.colormod[3] < 1)
7751         {
7752                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7753                 GL_DepthMask(false);
7754         }
7755         else
7756         {
7757                 GL_BlendFunc(GL_ONE, GL_ZERO);
7758                 GL_DepthMask(true);
7759         }
7760         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7761         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7762         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7763         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7764         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7765         for (i = 0, c = color4f;i < 6;i++, c += 4)
7766         {
7767                 c[0] *= rsurface.colormod[0];
7768                 c[1] *= rsurface.colormod[1];
7769                 c[2] *= rsurface.colormod[2];
7770                 c[3] *= rsurface.colormod[3];
7771         }
7772         if (r_refdef.fogenabled)
7773         {
7774                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7775                 {
7776                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7777                         f2 = 1 - f1;
7778                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7779                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7780                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7781                 }
7782         }
7783 //      R_Mesh_ResetTextureState();
7784         R_SetupShader_Generic_NoTexture(false, false);
7785         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7786         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7787 }
7788
7789 void R_DrawNoModel(entity_render_t *ent)
7790 {
7791         vec3_t org;
7792         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7793         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7794                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7795         else
7796                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7797 }
7798
7799 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7800 {
7801         vec3_t right1, right2, diff, normal;
7802
7803         VectorSubtract (org2, org1, normal);
7804
7805         // calculate 'right' vector for start
7806         VectorSubtract (r_refdef.view.origin, org1, diff);
7807         CrossProduct (normal, diff, right1);
7808         VectorNormalize (right1);
7809
7810         // calculate 'right' vector for end
7811         VectorSubtract (r_refdef.view.origin, org2, diff);
7812         CrossProduct (normal, diff, right2);
7813         VectorNormalize (right2);
7814
7815         vert[ 0] = org1[0] + width * right1[0];
7816         vert[ 1] = org1[1] + width * right1[1];
7817         vert[ 2] = org1[2] + width * right1[2];
7818         vert[ 3] = org1[0] - width * right1[0];
7819         vert[ 4] = org1[1] - width * right1[1];
7820         vert[ 5] = org1[2] - width * right1[2];
7821         vert[ 6] = org2[0] - width * right2[0];
7822         vert[ 7] = org2[1] - width * right2[1];
7823         vert[ 8] = org2[2] - width * right2[2];
7824         vert[ 9] = org2[0] + width * right2[0];
7825         vert[10] = org2[1] + width * right2[1];
7826         vert[11] = org2[2] + width * right2[2];
7827 }
7828
7829 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)
7830 {
7831         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7832         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7833         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7834         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7835         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7836         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7837         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7838         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7839         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7840         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7841         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7842         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7843 }
7844
7845 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7846 {
7847         int i;
7848         float *vertex3f;
7849         float v[3];
7850         VectorSet(v, x, y, z);
7851         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7852                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7853                         break;
7854         if (i == mesh->numvertices)
7855         {
7856                 if (mesh->numvertices < mesh->maxvertices)
7857                 {
7858                         VectorCopy(v, vertex3f);
7859                         mesh->numvertices++;
7860                 }
7861                 return mesh->numvertices;
7862         }
7863         else
7864                 return i;
7865 }
7866
7867 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7868 {
7869         int i;
7870         int *e, element[3];
7871         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7872         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7873         e = mesh->element3i + mesh->numtriangles * 3;
7874         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7875         {
7876                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7877                 if (mesh->numtriangles < mesh->maxtriangles)
7878                 {
7879                         *e++ = element[0];
7880                         *e++ = element[1];
7881                         *e++ = element[2];
7882                         mesh->numtriangles++;
7883                 }
7884                 element[1] = element[2];
7885         }
7886 }
7887
7888 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7889 {
7890         int i;
7891         int *e, element[3];
7892         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7893         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7894         e = mesh->element3i + mesh->numtriangles * 3;
7895         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7896         {
7897                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7898                 if (mesh->numtriangles < mesh->maxtriangles)
7899                 {
7900                         *e++ = element[0];
7901                         *e++ = element[1];
7902                         *e++ = element[2];
7903                         mesh->numtriangles++;
7904                 }
7905                 element[1] = element[2];
7906         }
7907 }
7908
7909 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7910 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7911 {
7912         int planenum, planenum2;
7913         int w;
7914         int tempnumpoints;
7915         mplane_t *plane, *plane2;
7916         double maxdist;
7917         double temppoints[2][256*3];
7918         // figure out how large a bounding box we need to properly compute this brush
7919         maxdist = 0;
7920         for (w = 0;w < numplanes;w++)
7921                 maxdist = max(maxdist, fabs(planes[w].dist));
7922         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7923         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7924         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7925         {
7926                 w = 0;
7927                 tempnumpoints = 4;
7928                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7929                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7930                 {
7931                         if (planenum2 == planenum)
7932                                 continue;
7933                         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);
7934                         w = !w;
7935                 }
7936                 if (tempnumpoints < 3)
7937                         continue;
7938                 // generate elements forming a triangle fan for this polygon
7939                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7940         }
7941 }
7942
7943 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)
7944 {
7945         texturelayer_t *layer;
7946         layer = t->currentlayers + t->currentnumlayers++;
7947         layer->type = type;
7948         layer->depthmask = depthmask;
7949         layer->blendfunc1 = blendfunc1;
7950         layer->blendfunc2 = blendfunc2;
7951         layer->texture = texture;
7952         layer->texmatrix = *matrix;
7953         layer->color[0] = r;
7954         layer->color[1] = g;
7955         layer->color[2] = b;
7956         layer->color[3] = a;
7957 }
7958
7959 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7960 {
7961         if(parms[0] == 0 && parms[1] == 0)
7962                 return false;
7963         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7964                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7965                         return false;
7966         return true;
7967 }
7968
7969 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7970 {
7971         double index, f;
7972         index = parms[2] + rsurface.shadertime * parms[3];
7973         index -= floor(index);
7974         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7975         {
7976         default:
7977         case Q3WAVEFUNC_NONE:
7978         case Q3WAVEFUNC_NOISE:
7979         case Q3WAVEFUNC_COUNT:
7980                 f = 0;
7981                 break;
7982         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7983         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7984         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7985         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7986         case Q3WAVEFUNC_TRIANGLE:
7987                 index *= 4;
7988                 f = index - floor(index);
7989                 if (index < 1)
7990                 {
7991                         // f = f;
7992                 }
7993                 else if (index < 2)
7994                         f = 1 - f;
7995                 else if (index < 3)
7996                         f = -f;
7997                 else
7998                         f = -(1 - f);
7999                 break;
8000         }
8001         f = parms[0] + parms[1] * f;
8002         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8003                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8004         return (float) f;
8005 }
8006
8007 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8008 {
8009         int w, h, idx;
8010         float shadertime;
8011         float f;
8012         float offsetd[2];
8013         float tcmat[12];
8014         matrix4x4_t matrix, temp;
8015         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8016         // it's better to have one huge fixup every 9 hours than gradual
8017         // degradation over time which looks consistently bad after many hours.
8018         //
8019         // tcmod scroll in particular suffers from this degradation which can't be
8020         // effectively worked around even with floor() tricks because we don't
8021         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8022         // a workaround involving floor() would be incorrect anyway...
8023         shadertime = rsurface.shadertime;
8024         if (shadertime >= 32768.0f)
8025                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8026         switch(tcmod->tcmod)
8027         {
8028                 case Q3TCMOD_COUNT:
8029                 case Q3TCMOD_NONE:
8030                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8031                                 matrix = r_waterscrollmatrix;
8032                         else
8033                                 matrix = identitymatrix;
8034                         break;
8035                 case Q3TCMOD_ENTITYTRANSLATE:
8036                         // this is used in Q3 to allow the gamecode to control texcoord
8037                         // scrolling on the entity, which is not supported in darkplaces yet.
8038                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8039                         break;
8040                 case Q3TCMOD_ROTATE:
8041                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8042                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8043                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8044                         break;
8045                 case Q3TCMOD_SCALE:
8046                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8047                         break;
8048                 case Q3TCMOD_SCROLL:
8049                         // this particular tcmod is a "bug for bug" compatible one with regards to
8050                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8051                         // specifically did the wrapping and so we must mimic that...
8052                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8053                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8054                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8055                         break;
8056                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8057                         w = (int) tcmod->parms[0];
8058                         h = (int) tcmod->parms[1];
8059                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8060                         f = f - floor(f);
8061                         idx = (int) floor(f * w * h);
8062                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8063                         break;
8064                 case Q3TCMOD_STRETCH:
8065                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8066                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8067                         break;
8068                 case Q3TCMOD_TRANSFORM:
8069                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8070                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8071                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8072                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8073                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8074                         break;
8075                 case Q3TCMOD_TURBULENT:
8076                         // this is handled in the RSurf_PrepareVertices function
8077                         matrix = identitymatrix;
8078                         break;
8079         }
8080         temp = *texmatrix;
8081         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8082 }
8083
8084 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8085 {
8086         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8087         char name[MAX_QPATH];
8088         skinframe_t *skinframe;
8089         unsigned char pixels[296*194];
8090         strlcpy(cache->name, skinname, sizeof(cache->name));
8091         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8092         if (developer_loading.integer)
8093                 Con_Printf("loading %s\n", name);
8094         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8095         if (!skinframe || !skinframe->base)
8096         {
8097                 unsigned char *f;
8098                 fs_offset_t filesize;
8099                 skinframe = NULL;
8100                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8101                 if (f)
8102                 {
8103                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8104                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8105                         Mem_Free(f);
8106                 }
8107         }
8108         cache->skinframe = skinframe;
8109 }
8110
8111 texture_t *R_GetCurrentTexture(texture_t *t)
8112 {
8113         int i;
8114         const entity_render_t *ent = rsurface.entity;
8115         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8116         q3shaderinfo_layer_tcmod_t *tcmod;
8117
8118         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8119                 return t->currentframe;
8120         t->update_lastrenderframe = r_textureframe;
8121         t->update_lastrenderentity = (void *)ent;
8122
8123         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8124                 t->camera_entity = ent->entitynumber;
8125         else
8126                 t->camera_entity = 0;
8127
8128         // switch to an alternate material if this is a q1bsp animated material
8129         {
8130                 texture_t *texture = t;
8131                 int s = rsurface.ent_skinnum;
8132                 if ((unsigned int)s >= (unsigned int)model->numskins)
8133                         s = 0;
8134                 if (model->skinscenes)
8135                 {
8136                         if (model->skinscenes[s].framecount > 1)
8137                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8138                         else
8139                                 s = model->skinscenes[s].firstframe;
8140                 }
8141                 if (s > 0)
8142                         t = t + s * model->num_surfaces;
8143                 if (t->animated)
8144                 {
8145                         // use an alternate animation if the entity's frame is not 0,
8146                         // and only if the texture has an alternate animation
8147                         if (t->animated == 2) // q2bsp
8148                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8149                         else if (rsurface.ent_alttextures && t->anim_total[1])
8150                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8151                         else
8152                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8153                 }
8154                 texture->currentframe = t;
8155         }
8156
8157         // update currentskinframe to be a qw skin or animation frame
8158         if (rsurface.ent_qwskin >= 0)
8159         {
8160                 i = rsurface.ent_qwskin;
8161                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8162                 {
8163                         r_qwskincache_size = cl.maxclients;
8164                         if (r_qwskincache)
8165                                 Mem_Free(r_qwskincache);
8166                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8167                 }
8168                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8169                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8170                 t->currentskinframe = r_qwskincache[i].skinframe;
8171                 if (t->currentskinframe == NULL)
8172                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8173         }
8174         else if (t->numskinframes >= 2)
8175                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8176         if (t->backgroundnumskinframes >= 2)
8177                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8178
8179         t->currentmaterialflags = t->basematerialflags;
8180         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8181         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8182                 t->currentalpha *= r_wateralpha.value;
8183         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8184                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8185         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8186                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8187         if (!(rsurface.ent_flags & RENDER_LIGHT))
8188                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8189         else if (FAKELIGHT_ENABLED)
8190         {
8191                 // no modellight if using fakelight for the map
8192         }
8193         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8194         {
8195                 // pick a model lighting mode
8196                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8197                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8198                 else
8199                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8200         }
8201         if (rsurface.ent_flags & RENDER_ADDITIVE)
8202                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8203         else if (t->currentalpha < 1)
8204                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8205         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8206         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8207                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8208         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8209                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8210         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8211                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8212         if (t->backgroundnumskinframes)
8213                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8214         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8215         {
8216                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8217                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8218         }
8219         else
8220                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8221         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8222         {
8223                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8224                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8225         }
8226         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8227                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8228
8229         // there is no tcmod
8230         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8231         {
8232                 t->currenttexmatrix = r_waterscrollmatrix;
8233                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8234         }
8235         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8236         {
8237                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8238                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8239         }
8240
8241         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8242                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8243         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8244                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8245
8246         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8247         if (t->currentskinframe->qpixels)
8248                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8249         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8250         if (!t->basetexture)
8251                 t->basetexture = r_texture_notexture;
8252         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8253         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8254         t->nmaptexture = t->currentskinframe->nmap;
8255         if (!t->nmaptexture)
8256                 t->nmaptexture = r_texture_blanknormalmap;
8257         t->glosstexture = r_texture_black;
8258         t->glowtexture = t->currentskinframe->glow;
8259         t->fogtexture = t->currentskinframe->fog;
8260         t->reflectmasktexture = t->currentskinframe->reflect;
8261         if (t->backgroundnumskinframes)
8262         {
8263                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8264                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8265                 t->backgroundglosstexture = r_texture_black;
8266                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8267                 if (!t->backgroundnmaptexture)
8268                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8269                 // make sure that if glow is going to be used, both textures are not NULL
8270                 if (!t->backgroundglowtexture && t->glowtexture)
8271                         t->backgroundglowtexture = r_texture_black;
8272                 if (!t->glowtexture && t->backgroundglowtexture)
8273                         t->glowtexture = r_texture_black;
8274         }
8275         else
8276         {
8277                 t->backgroundbasetexture = r_texture_white;
8278                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8279                 t->backgroundglosstexture = r_texture_black;
8280                 t->backgroundglowtexture = NULL;
8281         }
8282         t->specularpower = r_shadow_glossexponent.value;
8283         // TODO: store reference values for these in the texture?
8284         t->specularscale = 0;
8285         if (r_shadow_gloss.integer > 0)
8286         {
8287                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8288                 {
8289                         if (r_shadow_glossintensity.value > 0)
8290                         {
8291                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8292                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8293                                 t->specularscale = r_shadow_glossintensity.value;
8294                         }
8295                 }
8296                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8297                 {
8298                         t->glosstexture = r_texture_white;
8299                         t->backgroundglosstexture = r_texture_white;
8300                         t->specularscale = r_shadow_gloss2intensity.value;
8301                         t->specularpower = r_shadow_gloss2exponent.value;
8302                 }
8303         }
8304         t->specularscale *= t->specularscalemod;
8305         t->specularpower *= t->specularpowermod;
8306         t->rtlightambient = 0;
8307
8308         // lightmaps mode looks bad with dlights using actual texturing, so turn
8309         // off the colormap and glossmap, but leave the normalmap on as it still
8310         // accurately represents the shading involved
8311         if (gl_lightmaps.integer)
8312         {
8313                 t->basetexture = r_texture_grey128;
8314                 t->pantstexture = r_texture_black;
8315                 t->shirttexture = r_texture_black;
8316                 if (gl_lightmaps.integer < 2)
8317                         t->nmaptexture = r_texture_blanknormalmap;
8318                 t->glosstexture = r_texture_black;
8319                 t->glowtexture = NULL;
8320                 t->fogtexture = NULL;
8321                 t->reflectmasktexture = NULL;
8322                 t->backgroundbasetexture = NULL;
8323                 if (gl_lightmaps.integer < 2)
8324                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8325                 t->backgroundglosstexture = r_texture_black;
8326                 t->backgroundglowtexture = NULL;
8327                 t->specularscale = 0;
8328                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8329         }
8330
8331         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8332         VectorClear(t->dlightcolor);
8333         t->currentnumlayers = 0;
8334         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8335         {
8336                 int blendfunc1, blendfunc2;
8337                 qboolean depthmask;
8338                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8339                 {
8340                         blendfunc1 = GL_SRC_ALPHA;
8341                         blendfunc2 = GL_ONE;
8342                 }
8343                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8344                 {
8345                         blendfunc1 = GL_SRC_ALPHA;
8346                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8347                 }
8348                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8349                 {
8350                         blendfunc1 = t->customblendfunc[0];
8351                         blendfunc2 = t->customblendfunc[1];
8352                 }
8353                 else
8354                 {
8355                         blendfunc1 = GL_ONE;
8356                         blendfunc2 = GL_ZERO;
8357                 }
8358                 // don't colormod evilblend textures
8359                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8360                         VectorSet(t->lightmapcolor, 1, 1, 1);
8361                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8362                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8363                 {
8364                         // fullbright is not affected by r_refdef.lightmapintensity
8365                         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]);
8366                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8367                                 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]);
8368                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8369                                 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]);
8370                 }
8371                 else
8372                 {
8373                         vec3_t ambientcolor;
8374                         float colorscale;
8375                         // set the color tint used for lights affecting this surface
8376                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8377                         colorscale = 2;
8378                         // q3bsp has no lightmap updates, so the lightstylevalue that
8379                         // would normally be baked into the lightmap must be
8380                         // applied to the color
8381                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8382                         if (model->type == mod_brushq3)
8383                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8384                         colorscale *= r_refdef.lightmapintensity;
8385                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8386                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8387                         // basic lit geometry
8388                         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]);
8389                         // add pants/shirt if needed
8390                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8391                                 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]);
8392                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8393                                 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]);
8394                         // now add ambient passes if needed
8395                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8396                         {
8397                                 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]);
8398                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8399                                         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]);
8400                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8401                                         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]);
8402                         }
8403                 }
8404                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8405                         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]);
8406                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8407                 {
8408                         // if this is opaque use alpha blend which will darken the earlier
8409                         // passes cheaply.
8410                         //
8411                         // if this is an alpha blended material, all the earlier passes
8412                         // were darkened by fog already, so we only need to add the fog
8413                         // color ontop through the fog mask texture
8414                         //
8415                         // if this is an additive blended material, all the earlier passes
8416                         // were darkened by fog already, and we should not add fog color
8417                         // (because the background was not darkened, there is no fog color
8418                         // that was lost behind it).
8419                         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]);
8420                 }
8421         }
8422
8423         return t->currentframe;
8424 }
8425
8426 rsurfacestate_t rsurface;
8427
8428 void RSurf_ActiveWorldEntity(void)
8429 {
8430         dp_model_t *model = r_refdef.scene.worldmodel;
8431         //if (rsurface.entity == r_refdef.scene.worldentity)
8432         //      return;
8433         rsurface.entity = r_refdef.scene.worldentity;
8434         rsurface.skeleton = NULL;
8435         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8436         rsurface.ent_skinnum = 0;
8437         rsurface.ent_qwskin = -1;
8438         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8439         rsurface.shadertime = r_refdef.scene.time;
8440         rsurface.matrix = identitymatrix;
8441         rsurface.inversematrix = identitymatrix;
8442         rsurface.matrixscale = 1;
8443         rsurface.inversematrixscale = 1;
8444         R_EntityMatrix(&identitymatrix);
8445         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8446         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8447         rsurface.fograngerecip = r_refdef.fograngerecip;
8448         rsurface.fogheightfade = r_refdef.fogheightfade;
8449         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8450         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8451         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8452         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8453         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8454         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8455         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8456         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8457         rsurface.colormod[3] = 1;
8458         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);
8459         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8460         rsurface.frameblend[0].lerp = 1;
8461         rsurface.ent_alttextures = false;
8462         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8463         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8464         rsurface.entityskeletaltransform3x4 = NULL;
8465         rsurface.entityskeletaltransform3x4buffer = NULL;
8466         rsurface.entityskeletaltransform3x4offset = 0;
8467         rsurface.entityskeletaltransform3x4size = 0;;
8468         rsurface.entityskeletalnumtransforms = 0;
8469         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8470         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8471         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8472         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8473         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8475         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8476         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8477         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8478         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8479         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8480         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8481         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8482         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8484         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8485         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8486         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8487         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8488         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8489         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8490         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8491         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8492         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8493         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8494         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8495         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8496         rsurface.modelelement3i = model->surfmesh.data_element3i;
8497         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8498         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8499         rsurface.modelelement3s = model->surfmesh.data_element3s;
8500         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8501         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8502         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8503         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8504         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8505         rsurface.modelsurfaces = model->data_surfaces;
8506         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8507         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8508         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8509         rsurface.modelgeneratedvertex = false;
8510         rsurface.batchgeneratedvertex = false;
8511         rsurface.batchfirstvertex = 0;
8512         rsurface.batchnumvertices = 0;
8513         rsurface.batchfirsttriangle = 0;
8514         rsurface.batchnumtriangles = 0;
8515         rsurface.batchvertex3f  = NULL;
8516         rsurface.batchvertex3f_vertexbuffer = NULL;
8517         rsurface.batchvertex3f_bufferoffset = 0;
8518         rsurface.batchsvector3f = NULL;
8519         rsurface.batchsvector3f_vertexbuffer = NULL;
8520         rsurface.batchsvector3f_bufferoffset = 0;
8521         rsurface.batchtvector3f = NULL;
8522         rsurface.batchtvector3f_vertexbuffer = NULL;
8523         rsurface.batchtvector3f_bufferoffset = 0;
8524         rsurface.batchnormal3f  = NULL;
8525         rsurface.batchnormal3f_vertexbuffer = NULL;
8526         rsurface.batchnormal3f_bufferoffset = 0;
8527         rsurface.batchlightmapcolor4f = NULL;
8528         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8529         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8530         rsurface.batchtexcoordtexture2f = NULL;
8531         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8532         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8533         rsurface.batchtexcoordlightmap2f = NULL;
8534         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8535         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8536         rsurface.batchskeletalindex4ub = NULL;
8537         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8538         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8539         rsurface.batchskeletalweight4ub = NULL;
8540         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8541         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8542         rsurface.batchvertexmesh = NULL;
8543         rsurface.batchvertexmesh_vertexbuffer = NULL;
8544         rsurface.batchvertexmesh_bufferoffset = 0;
8545         rsurface.batchelement3i = NULL;
8546         rsurface.batchelement3i_indexbuffer = NULL;
8547         rsurface.batchelement3i_bufferoffset = 0;
8548         rsurface.batchelement3s = NULL;
8549         rsurface.batchelement3s_indexbuffer = NULL;
8550         rsurface.batchelement3s_bufferoffset = 0;
8551         rsurface.passcolor4f = NULL;
8552         rsurface.passcolor4f_vertexbuffer = NULL;
8553         rsurface.passcolor4f_bufferoffset = 0;
8554         rsurface.forcecurrenttextureupdate = false;
8555 }
8556
8557 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8558 {
8559         dp_model_t *model = ent->model;
8560         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8561         //      return;
8562         rsurface.entity = (entity_render_t *)ent;
8563         rsurface.skeleton = ent->skeleton;
8564         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8565         rsurface.ent_skinnum = ent->skinnum;
8566         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;
8567         rsurface.ent_flags = ent->flags;
8568         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8569         rsurface.matrix = ent->matrix;
8570         rsurface.inversematrix = ent->inversematrix;
8571         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8572         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8573         R_EntityMatrix(&rsurface.matrix);
8574         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8575         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8576         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8577         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8578         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8579         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8580         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8581         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8582         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8583         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8584         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8585         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8586         rsurface.colormod[3] = ent->alpha;
8587         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8588         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8589         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8590         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8591         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8592         if (ent->model->brush.submodel && !prepass)
8593         {
8594                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8595                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8596         }
8597         // if the animcache code decided it should use the shader path, skip the deform step
8598         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8599         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8600         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8601         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8602         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8603         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8604         {
8605                 if (ent->animcache_vertex3f)
8606                 {
8607                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8608                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8609                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8610                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8611                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8612                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8613                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8614                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8615                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8616                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8617                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8618                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8619                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8620                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8621                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8622                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8623                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8624                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8625                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8626                 }
8627                 else if (wanttangents)
8628                 {
8629                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8630                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8631                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8632                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8633                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8634                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8635                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8636                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8637                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8638                         rsurface.modelvertexmesh = NULL;
8639                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8640                         rsurface.modelvertexmesh_bufferoffset = 0;
8641                         rsurface.modelvertex3f_vertexbuffer = NULL;
8642                         rsurface.modelvertex3f_bufferoffset = 0;
8643                         rsurface.modelvertex3f_vertexbuffer = 0;
8644                         rsurface.modelvertex3f_bufferoffset = 0;
8645                         rsurface.modelsvector3f_vertexbuffer = 0;
8646                         rsurface.modelsvector3f_bufferoffset = 0;
8647                         rsurface.modeltvector3f_vertexbuffer = 0;
8648                         rsurface.modeltvector3f_bufferoffset = 0;
8649                         rsurface.modelnormal3f_vertexbuffer = 0;
8650                         rsurface.modelnormal3f_bufferoffset = 0;
8651                 }
8652                 else if (wantnormals)
8653                 {
8654                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8655                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8656                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8657                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8658                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8659                         rsurface.modelsvector3f = NULL;
8660                         rsurface.modeltvector3f = NULL;
8661                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8662                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8663                         rsurface.modelvertexmesh = NULL;
8664                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8665                         rsurface.modelvertexmesh_bufferoffset = 0;
8666                         rsurface.modelvertex3f_vertexbuffer = NULL;
8667                         rsurface.modelvertex3f_bufferoffset = 0;
8668                         rsurface.modelvertex3f_vertexbuffer = 0;
8669                         rsurface.modelvertex3f_bufferoffset = 0;
8670                         rsurface.modelsvector3f_vertexbuffer = 0;
8671                         rsurface.modelsvector3f_bufferoffset = 0;
8672                         rsurface.modeltvector3f_vertexbuffer = 0;
8673                         rsurface.modeltvector3f_bufferoffset = 0;
8674                         rsurface.modelnormal3f_vertexbuffer = 0;
8675                         rsurface.modelnormal3f_bufferoffset = 0;
8676                 }
8677                 else
8678                 {
8679                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8680                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8681                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8682                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8683                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8684                         rsurface.modelsvector3f = NULL;
8685                         rsurface.modeltvector3f = NULL;
8686                         rsurface.modelnormal3f = NULL;
8687                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8688                         rsurface.modelvertexmesh = NULL;
8689                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8690                         rsurface.modelvertexmesh_bufferoffset = 0;
8691                         rsurface.modelvertex3f_vertexbuffer = NULL;
8692                         rsurface.modelvertex3f_bufferoffset = 0;
8693                         rsurface.modelvertex3f_vertexbuffer = 0;
8694                         rsurface.modelvertex3f_bufferoffset = 0;
8695                         rsurface.modelsvector3f_vertexbuffer = 0;
8696                         rsurface.modelsvector3f_bufferoffset = 0;
8697                         rsurface.modeltvector3f_vertexbuffer = 0;
8698                         rsurface.modeltvector3f_bufferoffset = 0;
8699                         rsurface.modelnormal3f_vertexbuffer = 0;
8700                         rsurface.modelnormal3f_bufferoffset = 0;
8701                 }
8702                 rsurface.modelgeneratedvertex = true;
8703         }
8704         else
8705         {
8706                 if (rsurface.entityskeletaltransform3x4)
8707                 {
8708                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8709                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8710                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8711                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8712                 }
8713                 else
8714                 {
8715                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8716                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8717                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8718                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8719                 }
8720                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8721                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8722                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8723                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8724                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8725                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8726                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8727                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8728                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8729                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8730                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8731                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8732                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8733                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8734                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8735                 rsurface.modelgeneratedvertex = false;
8736         }
8737         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8738         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8739         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8740         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8741         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8742         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8743         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8744         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8745         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8746         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8747         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8748         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8749         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8750         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8751         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8752         rsurface.modelelement3i = model->surfmesh.data_element3i;
8753         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8754         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8755         rsurface.modelelement3s = model->surfmesh.data_element3s;
8756         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8757         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8758         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8759         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8760         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8761         rsurface.modelsurfaces = model->data_surfaces;
8762         rsurface.batchgeneratedvertex = false;
8763         rsurface.batchfirstvertex = 0;
8764         rsurface.batchnumvertices = 0;
8765         rsurface.batchfirsttriangle = 0;
8766         rsurface.batchnumtriangles = 0;
8767         rsurface.batchvertex3f  = NULL;
8768         rsurface.batchvertex3f_vertexbuffer = NULL;
8769         rsurface.batchvertex3f_bufferoffset = 0;
8770         rsurface.batchsvector3f = NULL;
8771         rsurface.batchsvector3f_vertexbuffer = NULL;
8772         rsurface.batchsvector3f_bufferoffset = 0;
8773         rsurface.batchtvector3f = NULL;
8774         rsurface.batchtvector3f_vertexbuffer = NULL;
8775         rsurface.batchtvector3f_bufferoffset = 0;
8776         rsurface.batchnormal3f  = NULL;
8777         rsurface.batchnormal3f_vertexbuffer = NULL;
8778         rsurface.batchnormal3f_bufferoffset = 0;
8779         rsurface.batchlightmapcolor4f = NULL;
8780         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8781         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8782         rsurface.batchtexcoordtexture2f = NULL;
8783         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8784         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8785         rsurface.batchtexcoordlightmap2f = NULL;
8786         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8787         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8788         rsurface.batchskeletalindex4ub = NULL;
8789         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8790         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8791         rsurface.batchskeletalweight4ub = NULL;
8792         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8793         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8794         rsurface.batchvertexmesh = NULL;
8795         rsurface.batchvertexmesh_vertexbuffer = NULL;
8796         rsurface.batchvertexmesh_bufferoffset = 0;
8797         rsurface.batchelement3i = NULL;
8798         rsurface.batchelement3i_indexbuffer = NULL;
8799         rsurface.batchelement3i_bufferoffset = 0;
8800         rsurface.batchelement3s = NULL;
8801         rsurface.batchelement3s_indexbuffer = NULL;
8802         rsurface.batchelement3s_bufferoffset = 0;
8803         rsurface.passcolor4f = NULL;
8804         rsurface.passcolor4f_vertexbuffer = NULL;
8805         rsurface.passcolor4f_bufferoffset = 0;
8806         rsurface.forcecurrenttextureupdate = false;
8807 }
8808
8809 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)
8810 {
8811         rsurface.entity = r_refdef.scene.worldentity;
8812         rsurface.skeleton = NULL;
8813         rsurface.ent_skinnum = 0;
8814         rsurface.ent_qwskin = -1;
8815         rsurface.ent_flags = entflags;
8816         rsurface.shadertime = r_refdef.scene.time - shadertime;
8817         rsurface.modelnumvertices = numvertices;
8818         rsurface.modelnumtriangles = numtriangles;
8819         rsurface.matrix = *matrix;
8820         rsurface.inversematrix = *inversematrix;
8821         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8822         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8823         R_EntityMatrix(&rsurface.matrix);
8824         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8825         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8826         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8827         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8828         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8829         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8830         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8831         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8832         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8833         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8834         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8835         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8836         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);
8837         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8838         rsurface.frameblend[0].lerp = 1;
8839         rsurface.ent_alttextures = false;
8840         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8841         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8842         rsurface.entityskeletaltransform3x4 = NULL;
8843         rsurface.entityskeletaltransform3x4buffer = NULL;
8844         rsurface.entityskeletaltransform3x4offset = 0;
8845         rsurface.entityskeletaltransform3x4size = 0;
8846         rsurface.entityskeletalnumtransforms = 0;
8847         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8848         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8849         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8850         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8851         if (wanttangents)
8852         {
8853                 rsurface.modelvertex3f = (float *)vertex3f;
8854                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8855                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8856                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8857         }
8858         else if (wantnormals)
8859         {
8860                 rsurface.modelvertex3f = (float *)vertex3f;
8861                 rsurface.modelsvector3f = NULL;
8862                 rsurface.modeltvector3f = NULL;
8863                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8864         }
8865         else
8866         {
8867                 rsurface.modelvertex3f = (float *)vertex3f;
8868                 rsurface.modelsvector3f = NULL;
8869                 rsurface.modeltvector3f = NULL;
8870                 rsurface.modelnormal3f = NULL;
8871         }
8872         rsurface.modelvertexmesh = NULL;
8873         rsurface.modelvertexmesh_vertexbuffer = NULL;
8874         rsurface.modelvertexmesh_bufferoffset = 0;
8875         rsurface.modelvertex3f_vertexbuffer = 0;
8876         rsurface.modelvertex3f_bufferoffset = 0;
8877         rsurface.modelsvector3f_vertexbuffer = 0;
8878         rsurface.modelsvector3f_bufferoffset = 0;
8879         rsurface.modeltvector3f_vertexbuffer = 0;
8880         rsurface.modeltvector3f_bufferoffset = 0;
8881         rsurface.modelnormal3f_vertexbuffer = 0;
8882         rsurface.modelnormal3f_bufferoffset = 0;
8883         rsurface.modelgeneratedvertex = true;
8884         rsurface.modellightmapcolor4f  = (float *)color4f;
8885         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8886         rsurface.modellightmapcolor4f_bufferoffset = 0;
8887         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8888         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8889         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8890         rsurface.modeltexcoordlightmap2f  = NULL;
8891         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8892         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8893         rsurface.modelskeletalindex4ub = NULL;
8894         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8895         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8896         rsurface.modelskeletalweight4ub = NULL;
8897         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8898         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8899         rsurface.modelelement3i = (int *)element3i;
8900         rsurface.modelelement3i_indexbuffer = NULL;
8901         rsurface.modelelement3i_bufferoffset = 0;
8902         rsurface.modelelement3s = (unsigned short *)element3s;
8903         rsurface.modelelement3s_indexbuffer = NULL;
8904         rsurface.modelelement3s_bufferoffset = 0;
8905         rsurface.modellightmapoffsets = NULL;
8906         rsurface.modelsurfaces = NULL;
8907         rsurface.batchgeneratedvertex = false;
8908         rsurface.batchfirstvertex = 0;
8909         rsurface.batchnumvertices = 0;
8910         rsurface.batchfirsttriangle = 0;
8911         rsurface.batchnumtriangles = 0;
8912         rsurface.batchvertex3f  = NULL;
8913         rsurface.batchvertex3f_vertexbuffer = NULL;
8914         rsurface.batchvertex3f_bufferoffset = 0;
8915         rsurface.batchsvector3f = NULL;
8916         rsurface.batchsvector3f_vertexbuffer = NULL;
8917         rsurface.batchsvector3f_bufferoffset = 0;
8918         rsurface.batchtvector3f = NULL;
8919         rsurface.batchtvector3f_vertexbuffer = NULL;
8920         rsurface.batchtvector3f_bufferoffset = 0;
8921         rsurface.batchnormal3f  = NULL;
8922         rsurface.batchnormal3f_vertexbuffer = NULL;
8923         rsurface.batchnormal3f_bufferoffset = 0;
8924         rsurface.batchlightmapcolor4f = NULL;
8925         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8926         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8927         rsurface.batchtexcoordtexture2f = NULL;
8928         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8929         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8930         rsurface.batchtexcoordlightmap2f = NULL;
8931         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8932         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8933         rsurface.batchskeletalindex4ub = NULL;
8934         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8935         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8936         rsurface.batchskeletalweight4ub = NULL;
8937         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8938         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8939         rsurface.batchvertexmesh = NULL;
8940         rsurface.batchvertexmesh_vertexbuffer = NULL;
8941         rsurface.batchvertexmesh_bufferoffset = 0;
8942         rsurface.batchelement3i = NULL;
8943         rsurface.batchelement3i_indexbuffer = NULL;
8944         rsurface.batchelement3i_bufferoffset = 0;
8945         rsurface.batchelement3s = NULL;
8946         rsurface.batchelement3s_indexbuffer = NULL;
8947         rsurface.batchelement3s_bufferoffset = 0;
8948         rsurface.passcolor4f = NULL;
8949         rsurface.passcolor4f_vertexbuffer = NULL;
8950         rsurface.passcolor4f_bufferoffset = 0;
8951         rsurface.forcecurrenttextureupdate = true;
8952
8953         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8954         {
8955                 if ((wantnormals || wanttangents) && !normal3f)
8956                 {
8957                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8958                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8959                 }
8960                 if (wanttangents && !svector3f)
8961                 {
8962                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8963                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8964                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8965                 }
8966         }
8967 }
8968
8969 float RSurf_FogPoint(const float *v)
8970 {
8971         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8972         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8973         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8974         float FogHeightFade = r_refdef.fogheightfade;
8975         float fogfrac;
8976         unsigned int fogmasktableindex;
8977         if (r_refdef.fogplaneviewabove)
8978                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8979         else
8980                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8981         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8982         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8983 }
8984
8985 float RSurf_FogVertex(const float *v)
8986 {
8987         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8988         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8989         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8990         float FogHeightFade = rsurface.fogheightfade;
8991         float fogfrac;
8992         unsigned int fogmasktableindex;
8993         if (r_refdef.fogplaneviewabove)
8994                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8995         else
8996                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8997         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8998         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8999 }
9000
9001 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9002 {
9003         int i;
9004         for (i = 0;i < numelements;i++)
9005                 outelement3i[i] = inelement3i[i] + adjust;
9006 }
9007
9008 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9009 extern cvar_t gl_vbo;
9010 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9011 {
9012         int deformindex;
9013         int firsttriangle;
9014         int numtriangles;
9015         int firstvertex;
9016         int endvertex;
9017         int numvertices;
9018         int surfacefirsttriangle;
9019         int surfacenumtriangles;
9020         int surfacefirstvertex;
9021         int surfaceendvertex;
9022         int surfacenumvertices;
9023         int batchnumsurfaces = texturenumsurfaces;
9024         int batchnumvertices;
9025         int batchnumtriangles;
9026         int needsupdate;
9027         int i, j;
9028         qboolean gaps;
9029         qboolean dynamicvertex;
9030         float amplitude;
9031         float animpos;
9032         float scale;
9033         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9034         float waveparms[4];
9035         unsigned char *ub;
9036         q3shaderinfo_deform_t *deform;
9037         const msurface_t *surface, *firstsurface;
9038         r_vertexmesh_t *vertexmesh;
9039         if (!texturenumsurfaces)
9040                 return;
9041         // find vertex range of this surface batch
9042         gaps = false;
9043         firstsurface = texturesurfacelist[0];
9044         firsttriangle = firstsurface->num_firsttriangle;
9045         batchnumvertices = 0;
9046         batchnumtriangles = 0;
9047         firstvertex = endvertex = firstsurface->num_firstvertex;
9048         for (i = 0;i < texturenumsurfaces;i++)
9049         {
9050                 surface = texturesurfacelist[i];
9051                 if (surface != firstsurface + i)
9052                         gaps = true;
9053                 surfacefirstvertex = surface->num_firstvertex;
9054                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9055                 surfacenumvertices = surface->num_vertices;
9056                 surfacenumtriangles = surface->num_triangles;
9057                 if (firstvertex > surfacefirstvertex)
9058                         firstvertex = surfacefirstvertex;
9059                 if (endvertex < surfaceendvertex)
9060                         endvertex = surfaceendvertex;
9061                 batchnumvertices += surfacenumvertices;
9062                 batchnumtriangles += surfacenumtriangles;
9063         }
9064
9065         r_refdef.stats[r_stat_batch_batches]++;
9066         if (gaps)
9067                 r_refdef.stats[r_stat_batch_withgaps]++;
9068         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9069         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9070         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9071
9072         // we now know the vertex range used, and if there are any gaps in it
9073         rsurface.batchfirstvertex = firstvertex;
9074         rsurface.batchnumvertices = endvertex - firstvertex;
9075         rsurface.batchfirsttriangle = firsttriangle;
9076         rsurface.batchnumtriangles = batchnumtriangles;
9077
9078         // this variable holds flags for which properties have been updated that
9079         // may require regenerating vertexmesh array...
9080         needsupdate = 0;
9081
9082         // check if any dynamic vertex processing must occur
9083         dynamicvertex = false;
9084
9085         // a cvar to force the dynamic vertex path to be taken, for debugging
9086         if (r_batch_debugdynamicvertexpath.integer)
9087         {
9088                 if (!dynamicvertex)
9089                 {
9090                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9091                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9092                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9093                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9094                 }
9095                 dynamicvertex = true;
9096         }
9097
9098         // if there is a chance of animated vertex colors, it's a dynamic batch
9099         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9100         {
9101                 if (!dynamicvertex)
9102                 {
9103                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9104                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9105                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9106                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9107                 }
9108                 dynamicvertex = true;
9109                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9110         }
9111
9112         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9113         {
9114                 switch (deform->deform)
9115                 {
9116                 default:
9117                 case Q3DEFORM_PROJECTIONSHADOW:
9118                 case Q3DEFORM_TEXT0:
9119                 case Q3DEFORM_TEXT1:
9120                 case Q3DEFORM_TEXT2:
9121                 case Q3DEFORM_TEXT3:
9122                 case Q3DEFORM_TEXT4:
9123                 case Q3DEFORM_TEXT5:
9124                 case Q3DEFORM_TEXT6:
9125                 case Q3DEFORM_TEXT7:
9126                 case Q3DEFORM_NONE:
9127                         break;
9128                 case Q3DEFORM_AUTOSPRITE:
9129                         if (!dynamicvertex)
9130                         {
9131                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9132                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9133                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9134                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9135                         }
9136                         dynamicvertex = true;
9137                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9138                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9139                         break;
9140                 case Q3DEFORM_AUTOSPRITE2:
9141                         if (!dynamicvertex)
9142                         {
9143                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9144                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9145                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9146                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9147                         }
9148                         dynamicvertex = true;
9149                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9150                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9151                         break;
9152                 case Q3DEFORM_NORMAL:
9153                         if (!dynamicvertex)
9154                         {
9155                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9156                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9157                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9158                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9159                         }
9160                         dynamicvertex = true;
9161                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9162                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9163                         break;
9164                 case Q3DEFORM_WAVE:
9165                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9166                                 break; // if wavefunc is a nop, ignore this transform
9167                         if (!dynamicvertex)
9168                         {
9169                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9170                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9171                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9172                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9173                         }
9174                         dynamicvertex = true;
9175                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9176                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9177                         break;
9178                 case Q3DEFORM_BULGE:
9179                         if (!dynamicvertex)
9180                         {
9181                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9182                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9183                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9184                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9185                         }
9186                         dynamicvertex = true;
9187                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9188                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9189                         break;
9190                 case Q3DEFORM_MOVE:
9191                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9192                                 break; // if wavefunc is a nop, ignore this transform
9193                         if (!dynamicvertex)
9194                         {
9195                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9196                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9197                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9198                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9199                         }
9200                         dynamicvertex = true;
9201                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9202                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9203                         break;
9204                 }
9205         }
9206         switch(rsurface.texture->tcgen.tcgen)
9207         {
9208         default:
9209         case Q3TCGEN_TEXTURE:
9210                 break;
9211         case Q3TCGEN_LIGHTMAP:
9212                 if (!dynamicvertex)
9213                 {
9214                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9215                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9216                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9217                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9218                 }
9219                 dynamicvertex = true;
9220                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9221                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9222                 break;
9223         case Q3TCGEN_VECTOR:
9224                 if (!dynamicvertex)
9225                 {
9226                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9227                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9228                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9229                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9230                 }
9231                 dynamicvertex = true;
9232                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9233                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9234                 break;
9235         case Q3TCGEN_ENVIRONMENT:
9236                 if (!dynamicvertex)
9237                 {
9238                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9239                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9240                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9241                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9242                 }
9243                 dynamicvertex = true;
9244                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9245                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9246                 break;
9247         }
9248         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9249         {
9250                 if (!dynamicvertex)
9251                 {
9252                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9253                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9254                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9255                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9256                 }
9257                 dynamicvertex = true;
9258                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9259                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9260         }
9261
9262         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9263         {
9264                 if (!dynamicvertex)
9265                 {
9266                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9267                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9268                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9269                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9270                 }
9271                 dynamicvertex = true;
9272                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9273         }
9274
9275         // when the model data has no vertex buffer (dynamic mesh), we need to
9276         // eliminate gaps
9277         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9278                 batchneed |= BATCHNEED_NOGAPS;
9279
9280         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9281         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9282         // we ensure this by treating the vertex batch as dynamic...
9283         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9284         {
9285                 if (!dynamicvertex)
9286                 {
9287                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9288                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9289                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9290                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9291                 }
9292                 dynamicvertex = true;
9293         }
9294
9295         if (dynamicvertex)
9296         {
9297                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9298                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9299                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9300                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9301                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9302                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9303                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9304                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9305         }
9306
9307         // if needsupdate, we have to do a dynamic vertex batch for sure
9308         if (needsupdate & batchneed)
9309         {
9310                 if (!dynamicvertex)
9311                 {
9312                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9313                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9314                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9315                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9316                 }
9317                 dynamicvertex = true;
9318         }
9319
9320         // see if we need to build vertexmesh from arrays
9321         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9322         {
9323                 if (!dynamicvertex)
9324                 {
9325                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9326                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9327                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9328                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9329                 }
9330                 dynamicvertex = true;
9331         }
9332
9333         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9334         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9335                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9336
9337         rsurface.batchvertex3f = rsurface.modelvertex3f;
9338         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9339         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9340         rsurface.batchsvector3f = rsurface.modelsvector3f;
9341         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9342         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9343         rsurface.batchtvector3f = rsurface.modeltvector3f;
9344         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9345         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9346         rsurface.batchnormal3f = rsurface.modelnormal3f;
9347         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9348         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9349         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9350         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9351         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9352         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9353         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9354         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9355         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9356         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9357         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9358         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9359         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9360         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9361         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9362         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9363         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9364         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9365         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9366         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9367         rsurface.batchelement3i = rsurface.modelelement3i;
9368         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9369         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9370         rsurface.batchelement3s = rsurface.modelelement3s;
9371         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9372         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9373         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9374         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9375         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9376         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9377         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9378
9379         // if any dynamic vertex processing has to occur in software, we copy the
9380         // entire surface list together before processing to rebase the vertices
9381         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9382         //
9383         // if any gaps exist and we do not have a static vertex buffer, we have to
9384         // copy the surface list together to avoid wasting upload bandwidth on the
9385         // vertices in the gaps.
9386         //
9387         // if gaps exist and we have a static vertex buffer, we can choose whether
9388         // to combine the index buffer ranges into one dynamic index buffer or
9389         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9390         //
9391         // in many cases the batch is reduced to one draw call.
9392
9393         rsurface.batchmultidraw = false;
9394         rsurface.batchmultidrawnumsurfaces = 0;
9395         rsurface.batchmultidrawsurfacelist = NULL;
9396
9397         if (!dynamicvertex)
9398         {
9399                 // static vertex data, just set pointers...
9400                 rsurface.batchgeneratedvertex = false;
9401                 // if there are gaps, we want to build a combined index buffer,
9402                 // otherwise use the original static buffer with an appropriate offset
9403                 if (gaps)
9404                 {
9405                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9406                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9407                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9408                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9409                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9410                         {
9411                                 rsurface.batchmultidraw = true;
9412                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9413                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9414                                 return;
9415                         }
9416                         // build a new triangle elements array for this batch
9417                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9418                         rsurface.batchfirsttriangle = 0;
9419                         numtriangles = 0;
9420                         for (i = 0;i < texturenumsurfaces;i++)
9421                         {
9422                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9423                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9424                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9425                                 numtriangles += surfacenumtriangles;
9426                         }
9427                         rsurface.batchelement3i_indexbuffer = NULL;
9428                         rsurface.batchelement3i_bufferoffset = 0;
9429                         rsurface.batchelement3s = NULL;
9430                         rsurface.batchelement3s_indexbuffer = NULL;
9431                         rsurface.batchelement3s_bufferoffset = 0;
9432                         if (endvertex <= 65536)
9433                         {
9434                                 // make a 16bit (unsigned short) index array if possible
9435                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9436                                 for (i = 0;i < numtriangles*3;i++)
9437                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9438                         }
9439                         // upload buffer data for the copytriangles batch
9440                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9441                         {
9442                                 if (rsurface.batchelement3s)
9443                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9444                                 else if (rsurface.batchelement3i)
9445                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9446                         }
9447                 }
9448                 else
9449                 {
9450                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9451                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9452                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9453                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9454                 }
9455                 return;
9456         }
9457
9458         // something needs software processing, do it for real...
9459         // we only directly handle separate array data in this case and then
9460         // generate interleaved data if needed...
9461         rsurface.batchgeneratedvertex = true;
9462         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9463         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9464         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9465         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9466
9467         // now copy the vertex data into a combined array and make an index array
9468         // (this is what Quake3 does all the time)
9469         // we also apply any skeletal animation here that would have been done in
9470         // the vertex shader, because most of the dynamic vertex animation cases
9471         // need actual vertex positions and normals
9472         //if (dynamicvertex)
9473         {
9474                 rsurface.batchvertexmesh = NULL;
9475                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9476                 rsurface.batchvertexmesh_bufferoffset = 0;
9477                 rsurface.batchvertex3f = NULL;
9478                 rsurface.batchvertex3f_vertexbuffer = NULL;
9479                 rsurface.batchvertex3f_bufferoffset = 0;
9480                 rsurface.batchsvector3f = NULL;
9481                 rsurface.batchsvector3f_vertexbuffer = NULL;
9482                 rsurface.batchsvector3f_bufferoffset = 0;
9483                 rsurface.batchtvector3f = NULL;
9484                 rsurface.batchtvector3f_vertexbuffer = NULL;
9485                 rsurface.batchtvector3f_bufferoffset = 0;
9486                 rsurface.batchnormal3f = NULL;
9487                 rsurface.batchnormal3f_vertexbuffer = NULL;
9488                 rsurface.batchnormal3f_bufferoffset = 0;
9489                 rsurface.batchlightmapcolor4f = NULL;
9490                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9491                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9492                 rsurface.batchtexcoordtexture2f = NULL;
9493                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9494                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9495                 rsurface.batchtexcoordlightmap2f = NULL;
9496                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9497                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9498                 rsurface.batchskeletalindex4ub = NULL;
9499                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9500                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9501                 rsurface.batchskeletalweight4ub = NULL;
9502                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9503                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9504                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9505                 rsurface.batchelement3i_indexbuffer = NULL;
9506                 rsurface.batchelement3i_bufferoffset = 0;
9507                 rsurface.batchelement3s = NULL;
9508                 rsurface.batchelement3s_indexbuffer = NULL;
9509                 rsurface.batchelement3s_bufferoffset = 0;
9510                 rsurface.batchskeletaltransform3x4buffer = NULL;
9511                 rsurface.batchskeletaltransform3x4offset = 0;
9512                 rsurface.batchskeletaltransform3x4size = 0;
9513                 // we'll only be setting up certain arrays as needed
9514                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9515                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9516                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9517                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9518                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9519                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9520                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9521                 {
9522                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9523                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9524                 }
9525                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9526                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9527                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9528                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9529                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9530                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9531                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9532                 {
9533                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9534                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9535                 }
9536                 numvertices = 0;
9537                 numtriangles = 0;
9538                 for (i = 0;i < texturenumsurfaces;i++)
9539                 {
9540                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9541                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9542                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9543                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9544                         // copy only the data requested
9545                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9546                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9547                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9548                         {
9549                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9550                                 {
9551                                         if (rsurface.batchvertex3f)
9552                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9553                                         else
9554                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9555                                 }
9556                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9557                                 {
9558                                         if (rsurface.modelnormal3f)
9559                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9560                                         else
9561                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9562                                 }
9563                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9564                                 {
9565                                         if (rsurface.modelsvector3f)
9566                                         {
9567                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9568                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9569                                         }
9570                                         else
9571                                         {
9572                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9573                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9574                                         }
9575                                 }
9576                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9577                                 {
9578                                         if (rsurface.modellightmapcolor4f)
9579                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9580                                         else
9581                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9582                                 }
9583                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9584                                 {
9585                                         if (rsurface.modeltexcoordtexture2f)
9586                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9587                                         else
9588                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9589                                 }
9590                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9591                                 {
9592                                         if (rsurface.modeltexcoordlightmap2f)
9593                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9594                                         else
9595                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9596                                 }
9597                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9598                                 {
9599                                         if (rsurface.modelskeletalindex4ub)
9600                                         {
9601                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9602                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9603                                         }
9604                                         else
9605                                         {
9606                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9607                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9608                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9609                                                 for (j = 0;j < surfacenumvertices;j++)
9610                                                         ub[j*4] = 255;
9611                                         }
9612                                 }
9613                         }
9614                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9615                         numvertices += surfacenumvertices;
9616                         numtriangles += surfacenumtriangles;
9617                 }
9618
9619                 // generate a 16bit index array as well if possible
9620                 // (in general, dynamic batches fit)
9621                 if (numvertices <= 65536)
9622                 {
9623                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9624                         for (i = 0;i < numtriangles*3;i++)
9625                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9626                 }
9627
9628                 // since we've copied everything, the batch now starts at 0
9629                 rsurface.batchfirstvertex = 0;
9630                 rsurface.batchnumvertices = batchnumvertices;
9631                 rsurface.batchfirsttriangle = 0;
9632                 rsurface.batchnumtriangles = batchnumtriangles;
9633         }
9634
9635         // apply skeletal animation that would have been done in the vertex shader
9636         if (rsurface.batchskeletaltransform3x4)
9637         {
9638                 const unsigned char *si;
9639                 const unsigned char *sw;
9640                 const float *t[4];
9641                 const float *b = rsurface.batchskeletaltransform3x4;
9642                 float *vp, *vs, *vt, *vn;
9643                 float w[4];
9644                 float m[3][4], n[3][4];
9645                 float tp[3], ts[3], tt[3], tn[3];
9646                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9647                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9648                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9649                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9650                 si = rsurface.batchskeletalindex4ub;
9651                 sw = rsurface.batchskeletalweight4ub;
9652                 vp = rsurface.batchvertex3f;
9653                 vs = rsurface.batchsvector3f;
9654                 vt = rsurface.batchtvector3f;
9655                 vn = rsurface.batchnormal3f;
9656                 memset(m[0], 0, sizeof(m));
9657                 memset(n[0], 0, sizeof(n));
9658                 for (i = 0;i < batchnumvertices;i++)
9659                 {
9660                         t[0] = b + si[0]*12;
9661                         if (sw[0] == 255)
9662                         {
9663                                 // common case - only one matrix
9664                                 m[0][0] = t[0][ 0];
9665                                 m[0][1] = t[0][ 1];
9666                                 m[0][2] = t[0][ 2];
9667                                 m[0][3] = t[0][ 3];
9668                                 m[1][0] = t[0][ 4];
9669                                 m[1][1] = t[0][ 5];
9670                                 m[1][2] = t[0][ 6];
9671                                 m[1][3] = t[0][ 7];
9672                                 m[2][0] = t[0][ 8];
9673                                 m[2][1] = t[0][ 9];
9674                                 m[2][2] = t[0][10];
9675                                 m[2][3] = t[0][11];
9676                         }
9677                         else if (sw[2] + sw[3])
9678                         {
9679                                 // blend 4 matrices
9680                                 t[1] = b + si[1]*12;
9681                                 t[2] = b + si[2]*12;
9682                                 t[3] = b + si[3]*12;
9683                                 w[0] = sw[0] * (1.0f / 255.0f);
9684                                 w[1] = sw[1] * (1.0f / 255.0f);
9685                                 w[2] = sw[2] * (1.0f / 255.0f);
9686                                 w[3] = sw[3] * (1.0f / 255.0f);
9687                                 // blend the matrices
9688                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9689                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9690                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9691                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9692                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9693                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9694                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9695                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9696                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9697                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9698                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9699                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9700                         }
9701                         else
9702                         {
9703                                 // blend 2 matrices
9704                                 t[1] = b + si[1]*12;
9705                                 w[0] = sw[0] * (1.0f / 255.0f);
9706                                 w[1] = sw[1] * (1.0f / 255.0f);
9707                                 // blend the matrices
9708                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9709                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9710                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9711                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9712                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9713                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9714                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9715                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9716                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9717                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9718                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9719                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9720                         }
9721                         si += 4;
9722                         sw += 4;
9723                         // modify the vertex
9724                         VectorCopy(vp, tp);
9725                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9726                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9727                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9728                         vp += 3;
9729                         if (vn)
9730                         {
9731                                 // the normal transformation matrix is a set of cross products...
9732                                 CrossProduct(m[1], m[2], n[0]);
9733                                 CrossProduct(m[2], m[0], n[1]);
9734                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9735                                 VectorCopy(vn, tn);
9736                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9737                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9738                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9739                                 VectorNormalize(vn);
9740                                 vn += 3;
9741                                 if (vs)
9742                                 {
9743                                         VectorCopy(vs, ts);
9744                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9745                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9746                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9747                                         VectorNormalize(vs);
9748                                         vs += 3;
9749                                         VectorCopy(vt, tt);
9750                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9751                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9752                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9753                                         VectorNormalize(vt);
9754                                         vt += 3;
9755                                 }
9756                         }
9757                 }
9758                 rsurface.batchskeletaltransform3x4 = NULL;
9759                 rsurface.batchskeletalnumtransforms = 0;
9760         }
9761
9762         // q1bsp surfaces rendered in vertex color mode have to have colors
9763         // calculated based on lightstyles
9764         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9765         {
9766                 // generate color arrays for the surfaces in this list
9767                 int c[4];
9768                 int scale;
9769                 int size3;
9770                 const int *offsets;
9771                 const unsigned char *lm;
9772                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9773                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9774                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9775                 numvertices = 0;
9776                 for (i = 0;i < texturenumsurfaces;i++)
9777                 {
9778                         surface = texturesurfacelist[i];
9779                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9780                         surfacenumvertices = surface->num_vertices;
9781                         if (surface->lightmapinfo->samples)
9782                         {
9783                                 for (j = 0;j < surfacenumvertices;j++)
9784                                 {
9785                                         lm = surface->lightmapinfo->samples + offsets[j];
9786                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9787                                         VectorScale(lm, scale, c);
9788                                         if (surface->lightmapinfo->styles[1] != 255)
9789                                         {
9790                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9791                                                 lm += size3;
9792                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9793                                                 VectorMA(c, scale, lm, c);
9794                                                 if (surface->lightmapinfo->styles[2] != 255)
9795                                                 {
9796                                                         lm += size3;
9797                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9798                                                         VectorMA(c, scale, lm, c);
9799                                                         if (surface->lightmapinfo->styles[3] != 255)
9800                                                         {
9801                                                                 lm += size3;
9802                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9803                                                                 VectorMA(c, scale, lm, c);
9804                                                         }
9805                                                 }
9806                                         }
9807                                         c[0] >>= 7;
9808                                         c[1] >>= 7;
9809                                         c[2] >>= 7;
9810                                         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);
9811                                         numvertices++;
9812                                 }
9813                         }
9814                         else
9815                         {
9816                                 for (j = 0;j < surfacenumvertices;j++)
9817                                 {
9818                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9819                                         numvertices++;
9820                                 }
9821                         }
9822                 }
9823         }
9824
9825         // if vertices are deformed (sprite flares and things in maps, possibly
9826         // water waves, bulges and other deformations), modify the copied vertices
9827         // in place
9828         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9829         {
9830                 switch (deform->deform)
9831                 {
9832                 default:
9833                 case Q3DEFORM_PROJECTIONSHADOW:
9834                 case Q3DEFORM_TEXT0:
9835                 case Q3DEFORM_TEXT1:
9836                 case Q3DEFORM_TEXT2:
9837                 case Q3DEFORM_TEXT3:
9838                 case Q3DEFORM_TEXT4:
9839                 case Q3DEFORM_TEXT5:
9840                 case Q3DEFORM_TEXT6:
9841                 case Q3DEFORM_TEXT7:
9842                 case Q3DEFORM_NONE:
9843                         break;
9844                 case Q3DEFORM_AUTOSPRITE:
9845                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9846                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9847                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9848                         VectorNormalize(newforward);
9849                         VectorNormalize(newright);
9850                         VectorNormalize(newup);
9851 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9852 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9853 //                      rsurface.batchvertex3f_bufferoffset = 0;
9854 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9855 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9856 //                      rsurface.batchsvector3f_bufferoffset = 0;
9857 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9858 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9859 //                      rsurface.batchtvector3f_bufferoffset = 0;
9860 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9861 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9862 //                      rsurface.batchnormal3f_bufferoffset = 0;
9863                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9864                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9865                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9866                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9867                                 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);
9868                         // a single autosprite surface can contain multiple sprites...
9869                         for (j = 0;j < batchnumvertices - 3;j += 4)
9870                         {
9871                                 VectorClear(center);
9872                                 for (i = 0;i < 4;i++)
9873                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9874                                 VectorScale(center, 0.25f, center);
9875                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9876                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9877                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9878                                 for (i = 0;i < 4;i++)
9879                                 {
9880                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9881                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9882                                 }
9883                         }
9884                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9885                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9886                         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);
9887                         break;
9888                 case Q3DEFORM_AUTOSPRITE2:
9889                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9890                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9891                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9892                         VectorNormalize(newforward);
9893                         VectorNormalize(newright);
9894                         VectorNormalize(newup);
9895 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9896 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9897 //                      rsurface.batchvertex3f_bufferoffset = 0;
9898                         {
9899                                 const float *v1, *v2;
9900                                 vec3_t start, end;
9901                                 float f, l;
9902                                 struct
9903                                 {
9904                                         float length2;
9905                                         const float *v1;
9906                                         const float *v2;
9907                                 }
9908                                 shortest[2];
9909                                 memset(shortest, 0, sizeof(shortest));
9910                                 // a single autosprite surface can contain multiple sprites...
9911                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9912                                 {
9913                                         VectorClear(center);
9914                                         for (i = 0;i < 4;i++)
9915                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9916                                         VectorScale(center, 0.25f, center);
9917                                         // find the two shortest edges, then use them to define the
9918                                         // axis vectors for rotating around the central axis
9919                                         for (i = 0;i < 6;i++)
9920                                         {
9921                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9922                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9923                                                 l = VectorDistance2(v1, v2);
9924                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9925                                                 if (v1[2] != v2[2])
9926                                                         l += (1.0f / 1024.0f);
9927                                                 if (shortest[0].length2 > l || i == 0)
9928                                                 {
9929                                                         shortest[1] = shortest[0];
9930                                                         shortest[0].length2 = l;
9931                                                         shortest[0].v1 = v1;
9932                                                         shortest[0].v2 = v2;
9933                                                 }
9934                                                 else if (shortest[1].length2 > l || i == 1)
9935                                                 {
9936                                                         shortest[1].length2 = l;
9937                                                         shortest[1].v1 = v1;
9938                                                         shortest[1].v2 = v2;
9939                                                 }
9940                                         }
9941                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9942                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9943                                         // this calculates the right vector from the shortest edge
9944                                         // and the up vector from the edge midpoints
9945                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9946                                         VectorNormalize(right);
9947                                         VectorSubtract(end, start, up);
9948                                         VectorNormalize(up);
9949                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9950                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9951                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9952                                         VectorNegate(forward, forward);
9953                                         VectorReflect(forward, 0, up, forward);
9954                                         VectorNormalize(forward);
9955                                         CrossProduct(up, forward, newright);
9956                                         VectorNormalize(newright);
9957                                         // rotate the quad around the up axis vector, this is made
9958                                         // especially easy by the fact we know the quad is flat,
9959                                         // so we only have to subtract the center position and
9960                                         // measure distance along the right vector, and then
9961                                         // multiply that by the newright vector and add back the
9962                                         // center position
9963                                         // we also need to subtract the old position to undo the
9964                                         // displacement from the center, which we do with a
9965                                         // DotProduct, the subtraction/addition of center is also
9966                                         // optimized into DotProducts here
9967                                         l = DotProduct(right, center);
9968                                         for (i = 0;i < 4;i++)
9969                                         {
9970                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9971                                                 f = DotProduct(right, v1) - l;
9972                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9973                                         }
9974                                 }
9975                         }
9976                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9977                         {
9978 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9979 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9980 //                              rsurface.batchnormal3f_bufferoffset = 0;
9981                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9982                         }
9983                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9984                         {
9985 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9986 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9987 //                              rsurface.batchsvector3f_bufferoffset = 0;
9988 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9989 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9990 //                              rsurface.batchtvector3f_bufferoffset = 0;
9991                                 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);
9992                         }
9993                         break;
9994                 case Q3DEFORM_NORMAL:
9995                         // deform the normals to make reflections wavey
9996                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9997                         rsurface.batchnormal3f_vertexbuffer = NULL;
9998                         rsurface.batchnormal3f_bufferoffset = 0;
9999                         for (j = 0;j < batchnumvertices;j++)
10000                         {
10001                                 float vertex[3];
10002                                 float *normal = rsurface.batchnormal3f + 3*j;
10003                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10004                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10005                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10006                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10007                                 VectorNormalize(normal);
10008                         }
10009                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10010                         {
10011 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10012 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10013 //                              rsurface.batchsvector3f_bufferoffset = 0;
10014 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10015 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10016 //                              rsurface.batchtvector3f_bufferoffset = 0;
10017                                 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);
10018                         }
10019                         break;
10020                 case Q3DEFORM_WAVE:
10021                         // deform vertex array to make wavey water and flags and such
10022                         waveparms[0] = deform->waveparms[0];
10023                         waveparms[1] = deform->waveparms[1];
10024                         waveparms[2] = deform->waveparms[2];
10025                         waveparms[3] = deform->waveparms[3];
10026                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10027                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10028                         // this is how a divisor of vertex influence on deformation
10029                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10030                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10031 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10032 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10033 //                      rsurface.batchvertex3f_bufferoffset = 0;
10034 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10035 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10036 //                      rsurface.batchnormal3f_bufferoffset = 0;
10037                         for (j = 0;j < batchnumvertices;j++)
10038                         {
10039                                 // if the wavefunc depends on time, evaluate it per-vertex
10040                                 if (waveparms[3])
10041                                 {
10042                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10043                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10044                                 }
10045                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10046                         }
10047                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10048                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10049                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10050                         {
10051 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10052 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10053 //                              rsurface.batchsvector3f_bufferoffset = 0;
10054 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10055 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10056 //                              rsurface.batchtvector3f_bufferoffset = 0;
10057                                 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);
10058                         }
10059                         break;
10060                 case Q3DEFORM_BULGE:
10061                         // deform vertex array to make the surface have moving bulges
10062 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10063 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10064 //                      rsurface.batchvertex3f_bufferoffset = 0;
10065 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10066 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10067 //                      rsurface.batchnormal3f_bufferoffset = 0;
10068                         for (j = 0;j < batchnumvertices;j++)
10069                         {
10070                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10071                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10072                         }
10073                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10074                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10075                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10076                         {
10077 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10078 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10079 //                              rsurface.batchsvector3f_bufferoffset = 0;
10080 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10081 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10082 //                              rsurface.batchtvector3f_bufferoffset = 0;
10083                                 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);
10084                         }
10085                         break;
10086                 case Q3DEFORM_MOVE:
10087                         // deform vertex array
10088                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10089                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10090                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10091                         VectorScale(deform->parms, scale, waveparms);
10092 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10093 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10094 //                      rsurface.batchvertex3f_bufferoffset = 0;
10095                         for (j = 0;j < batchnumvertices;j++)
10096                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10097                         break;
10098                 }
10099         }
10100
10101         if (rsurface.batchtexcoordtexture2f)
10102         {
10103         // generate texcoords based on the chosen texcoord source
10104                 switch(rsurface.texture->tcgen.tcgen)
10105                 {
10106                 default:
10107                 case Q3TCGEN_TEXTURE:
10108                         break;
10109                 case Q3TCGEN_LIGHTMAP:
10110         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10111         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10112         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10113                         if (rsurface.batchtexcoordlightmap2f)
10114                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10115                         break;
10116                 case Q3TCGEN_VECTOR:
10117         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10118         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10119         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10120                         for (j = 0;j < batchnumvertices;j++)
10121                         {
10122                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10123                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10124                         }
10125                         break;
10126                 case Q3TCGEN_ENVIRONMENT:
10127                         // make environment reflections using a spheremap
10128                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10129                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10130                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10131                         for (j = 0;j < batchnumvertices;j++)
10132                         {
10133                                 // identical to Q3A's method, but executed in worldspace so
10134                                 // carried models can be shiny too
10135
10136                                 float viewer[3], d, reflected[3], worldreflected[3];
10137
10138                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10139                                 // VectorNormalize(viewer);
10140
10141                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10142
10143                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10144                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10145                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10146                                 // note: this is proportinal to viewer, so we can normalize later
10147
10148                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10149                                 VectorNormalize(worldreflected);
10150
10151                                 // note: this sphere map only uses world x and z!
10152                                 // so positive and negative y will LOOK THE SAME.
10153                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10154                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10155                         }
10156                         break;
10157                 }
10158                 // the only tcmod that needs software vertex processing is turbulent, so
10159                 // check for it here and apply the changes if needed
10160                 // and we only support that as the first one
10161                 // (handling a mixture of turbulent and other tcmods would be problematic
10162                 //  without punting it entirely to a software path)
10163                 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10164                 {
10165                         amplitude = rsurface.texture->tcmods[0].parms[1];
10166                         animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10167         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10168         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10169         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10170                         for (j = 0;j < batchnumvertices;j++)
10171                         {
10172                                 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);
10173                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10174                         }
10175                 }
10176         }
10177
10178         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10179         {
10180                 // convert the modified arrays to vertex structs
10181 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10182 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10183 //              rsurface.batchvertexmesh_bufferoffset = 0;
10184                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10185                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10186                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10187                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10188                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10189                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10190                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10191                 {
10192                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10193                         {
10194                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10195                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10196                         }
10197                 }
10198                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10199                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10200                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10201                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10202                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10203                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10204                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10205                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10206                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10207                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10208                 {
10209                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10210                         {
10211                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10212                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10213                         }
10214                 }
10215         }
10216
10217         // upload buffer data for the dynamic batch
10218         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10219         {
10220                 if (rsurface.batchvertexmesh)
10221                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10222                 else
10223                 {
10224                         if (rsurface.batchvertex3f)
10225                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10226                         if (rsurface.batchsvector3f)
10227                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10228                         if (rsurface.batchtvector3f)
10229                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10230                         if (rsurface.batchnormal3f)
10231                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10232                         if (rsurface.batchlightmapcolor4f)
10233                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10234                         if (rsurface.batchtexcoordtexture2f)
10235                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10236                         if (rsurface.batchtexcoordlightmap2f)
10237                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10238                         if (rsurface.batchskeletalindex4ub)
10239                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10240                         if (rsurface.batchskeletalweight4ub)
10241                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10242                 }
10243                 if (rsurface.batchelement3s)
10244                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10245                 else if (rsurface.batchelement3i)
10246                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10247         }
10248 }
10249
10250 void RSurf_DrawBatch(void)
10251 {
10252         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10253         // through the pipeline, killing it earlier in the pipeline would have
10254         // per-surface overhead rather than per-batch overhead, so it's best to
10255         // reject it here, before it hits glDraw.
10256         if (rsurface.batchnumtriangles == 0)
10257                 return;
10258 #if 0
10259         // batch debugging code
10260         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10261         {
10262                 int i;
10263                 int j;
10264                 int c;
10265                 const int *e;
10266                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10267                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10268                 {
10269                         c = e[i];
10270                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10271                         {
10272                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10273                                 {
10274                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10275                                                 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);
10276                                         break;
10277                                 }
10278                         }
10279                 }
10280         }
10281 #endif
10282         if (rsurface.batchmultidraw)
10283         {
10284                 // issue multiple draws rather than copying index data
10285                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10286                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10287                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10288                 for (i = 0;i < numsurfaces;)
10289                 {
10290                         // combine consecutive surfaces as one draw
10291                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10292                                 if (surfacelist[j] != surfacelist[k] + 1)
10293                                         break;
10294                         firstvertex = surfacelist[i]->num_firstvertex;
10295                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10296                         firsttriangle = surfacelist[i]->num_firsttriangle;
10297                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10298                         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);
10299                         i = j;
10300                 }
10301         }
10302         else
10303         {
10304                 // there is only one consecutive run of index data (may have been combined)
10305                 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);
10306         }
10307 }
10308
10309 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10310 {
10311         // pick the closest matching water plane
10312         int planeindex, vertexindex, bestplaneindex = -1;
10313         float d, bestd;
10314         vec3_t vert;
10315         const float *v;
10316         r_waterstate_waterplane_t *p;
10317         qboolean prepared = false;
10318         bestd = 0;
10319         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10320         {
10321                 if(p->camera_entity != rsurface.texture->camera_entity)
10322                         continue;
10323                 d = 0;
10324                 if(!prepared)
10325                 {
10326                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10327                         prepared = true;
10328                         if(rsurface.batchnumvertices == 0)
10329                                 break;
10330                 }
10331                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10332                 {
10333                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10334                         d += fabs(PlaneDiff(vert, &p->plane));
10335                 }
10336                 if (bestd > d || bestplaneindex < 0)
10337                 {
10338                         bestd = d;
10339                         bestplaneindex = planeindex;
10340                 }
10341         }
10342         return bestplaneindex;
10343         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10344         // this situation though, as it might be better to render single larger
10345         // batches with useless stuff (backface culled for example) than to
10346         // render multiple smaller batches
10347 }
10348
10349 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10350 {
10351         int i;
10352         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10353         rsurface.passcolor4f_vertexbuffer = 0;
10354         rsurface.passcolor4f_bufferoffset = 0;
10355         for (i = 0;i < rsurface.batchnumvertices;i++)
10356                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10357 }
10358
10359 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10360 {
10361         int i;
10362         float f;
10363         const float *v;
10364         const float *c;
10365         float *c2;
10366         if (rsurface.passcolor4f)
10367         {
10368                 // generate color arrays
10369                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10370                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10371                 rsurface.passcolor4f_vertexbuffer = 0;
10372                 rsurface.passcolor4f_bufferoffset = 0;
10373                 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)
10374                 {
10375                         f = RSurf_FogVertex(v);
10376                         c2[0] = c[0] * f;
10377                         c2[1] = c[1] * f;
10378                         c2[2] = c[2] * f;
10379                         c2[3] = c[3];
10380                 }
10381         }
10382         else
10383         {
10384                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10385                 rsurface.passcolor4f_vertexbuffer = 0;
10386                 rsurface.passcolor4f_bufferoffset = 0;
10387                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10388                 {
10389                         f = RSurf_FogVertex(v);
10390                         c2[0] = f;
10391                         c2[1] = f;
10392                         c2[2] = f;
10393                         c2[3] = 1;
10394                 }
10395         }
10396 }
10397
10398 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10399 {
10400         int i;
10401         float f;
10402         const float *v;
10403         const float *c;
10404         float *c2;
10405         if (!rsurface.passcolor4f)
10406                 return;
10407         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10408         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10409         rsurface.passcolor4f_vertexbuffer = 0;
10410         rsurface.passcolor4f_bufferoffset = 0;
10411         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)
10412         {
10413                 f = RSurf_FogVertex(v);
10414                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10415                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10416                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10417                 c2[3] = c[3];
10418         }
10419 }
10420
10421 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10422 {
10423         int i;
10424         const float *c;
10425         float *c2;
10426         if (!rsurface.passcolor4f)
10427                 return;
10428         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10429         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10430         rsurface.passcolor4f_vertexbuffer = 0;
10431         rsurface.passcolor4f_bufferoffset = 0;
10432         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10433         {
10434                 c2[0] = c[0] * r;
10435                 c2[1] = c[1] * g;
10436                 c2[2] = c[2] * b;
10437                 c2[3] = c[3] * a;
10438         }
10439 }
10440
10441 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10442 {
10443         int i;
10444         const float *c;
10445         float *c2;
10446         if (!rsurface.passcolor4f)
10447                 return;
10448         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10449         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10450         rsurface.passcolor4f_vertexbuffer = 0;
10451         rsurface.passcolor4f_bufferoffset = 0;
10452         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10453         {
10454                 c2[0] = c[0] + r_refdef.scene.ambient;
10455                 c2[1] = c[1] + r_refdef.scene.ambient;
10456                 c2[2] = c[2] + r_refdef.scene.ambient;
10457                 c2[3] = c[3];
10458         }
10459 }
10460
10461 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10462 {
10463         // TODO: optimize
10464         rsurface.passcolor4f = NULL;
10465         rsurface.passcolor4f_vertexbuffer = 0;
10466         rsurface.passcolor4f_bufferoffset = 0;
10467         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10468         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10469         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10470         GL_Color(r, g, b, a);
10471         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10472         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10473         R_Mesh_TexMatrix(0, NULL);
10474         RSurf_DrawBatch();
10475 }
10476
10477 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10478 {
10479         // TODO: optimize applyfog && applycolor case
10480         // just apply fog if necessary, and tint the fog color array if necessary
10481         rsurface.passcolor4f = NULL;
10482         rsurface.passcolor4f_vertexbuffer = 0;
10483         rsurface.passcolor4f_bufferoffset = 0;
10484         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10485         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10486         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10487         GL_Color(r, g, b, a);
10488         RSurf_DrawBatch();
10489 }
10490
10491 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10492 {
10493         // TODO: optimize
10494         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10495         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10496         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10497         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10498         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10499         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10500         GL_Color(r, g, b, a);
10501         RSurf_DrawBatch();
10502 }
10503
10504 static void RSurf_DrawBatch_GL11_ClampColor(void)
10505 {
10506         int i;
10507         const float *c1;
10508         float *c2;
10509         if (!rsurface.passcolor4f)
10510                 return;
10511         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10512         {
10513                 c2[0] = bound(0.0f, c1[0], 1.0f);
10514                 c2[1] = bound(0.0f, c1[1], 1.0f);
10515                 c2[2] = bound(0.0f, c1[2], 1.0f);
10516                 c2[3] = bound(0.0f, c1[3], 1.0f);
10517         }
10518 }
10519
10520 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10521 {
10522         int i;
10523         float f;
10524         const float *v;
10525         const float *n;
10526         float *c;
10527         //vec3_t eyedir;
10528
10529         // fake shading
10530         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10531         rsurface.passcolor4f_vertexbuffer = 0;
10532         rsurface.passcolor4f_bufferoffset = 0;
10533         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
10534         {
10535                 f = -DotProduct(r_refdef.view.forward, n);
10536                 f = max(0, f);
10537                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10538                 f *= r_refdef.lightmapintensity;
10539                 Vector4Set(c, f, f, f, 1);
10540         }
10541 }
10542
10543 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10544 {
10545         RSurf_DrawBatch_GL11_ApplyFakeLight();
10546         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10547         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10548         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10549         GL_Color(r, g, b, a);
10550         RSurf_DrawBatch();
10551 }
10552
10553 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10554 {
10555         int i;
10556         float f;
10557         float alpha;
10558         const float *v;
10559         const float *n;
10560         float *c;
10561         vec3_t ambientcolor;
10562         vec3_t diffusecolor;
10563         vec3_t lightdir;
10564         // TODO: optimize
10565         // model lighting
10566         VectorCopy(rsurface.modellight_lightdir, lightdir);
10567         f = 0.5f * r_refdef.lightmapintensity;
10568         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10569         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10570         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10571         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10572         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10573         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10574         alpha = *a;
10575         if (VectorLength2(diffusecolor) > 0)
10576         {
10577                 // q3-style directional shading
10578                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10579                 rsurface.passcolor4f_vertexbuffer = 0;
10580                 rsurface.passcolor4f_bufferoffset = 0;
10581                 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)
10582                 {
10583                         if ((f = DotProduct(n, lightdir)) > 0)
10584                                 VectorMA(ambientcolor, f, diffusecolor, c);
10585                         else
10586                                 VectorCopy(ambientcolor, c);
10587                         c[3] = alpha;
10588                 }
10589                 *r = 1;
10590                 *g = 1;
10591                 *b = 1;
10592                 *a = 1;
10593                 *applycolor = false;
10594         }
10595         else
10596         {
10597                 *r = ambientcolor[0];
10598                 *g = ambientcolor[1];
10599                 *b = ambientcolor[2];
10600                 rsurface.passcolor4f = NULL;
10601                 rsurface.passcolor4f_vertexbuffer = 0;
10602                 rsurface.passcolor4f_bufferoffset = 0;
10603         }
10604 }
10605
10606 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10607 {
10608         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10609         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10610         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10611         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10612         GL_Color(r, g, b, a);
10613         RSurf_DrawBatch();
10614 }
10615
10616 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10617 {
10618         int i;
10619         float f;
10620         const float *v;
10621         float *c;
10622
10623         // fake shading
10624         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10625         rsurface.passcolor4f_vertexbuffer = 0;
10626         rsurface.passcolor4f_bufferoffset = 0;
10627
10628         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10629         {
10630                 f = 1 - RSurf_FogVertex(v);
10631                 c[0] = r;
10632                 c[1] = g;
10633                 c[2] = b;
10634                 c[3] = f * a;
10635         }
10636 }
10637
10638 void RSurf_SetupDepthAndCulling(void)
10639 {
10640         // submodels are biased to avoid z-fighting with world surfaces that they
10641         // may be exactly overlapping (avoids z-fighting artifacts on certain
10642         // doors and things in Quake maps)
10643         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10644         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10645         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10646         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10647 }
10648
10649 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10650 {
10651         // transparent sky would be ridiculous
10652         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10653                 return;
10654         R_SetupShader_Generic_NoTexture(false, false);
10655         skyrenderlater = true;
10656         RSurf_SetupDepthAndCulling();
10657         GL_DepthMask(true);
10658         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10659         // skymasking on them, and Quake3 never did sky masking (unlike
10660         // software Quake and software Quake2), so disable the sky masking
10661         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10662         // and skymasking also looks very bad when noclipping outside the
10663         // level, so don't use it then either.
10664         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10665         {
10666                 R_Mesh_ResetTextureState();
10667                 if (skyrendermasked)
10668                 {
10669                         R_SetupShader_DepthOrShadow(false, false, false);
10670                         // depth-only (masking)
10671                         GL_ColorMask(0,0,0,0);
10672                         // just to make sure that braindead drivers don't draw
10673                         // anything despite that colormask...
10674                         GL_BlendFunc(GL_ZERO, GL_ONE);
10675                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10676                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10677                 }
10678                 else
10679                 {
10680                         R_SetupShader_Generic_NoTexture(false, false);
10681                         // fog sky
10682                         GL_BlendFunc(GL_ONE, GL_ZERO);
10683                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10684                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10685                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10686                 }
10687                 RSurf_DrawBatch();
10688                 if (skyrendermasked)
10689                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10690         }
10691         R_Mesh_ResetTextureState();
10692         GL_Color(1, 1, 1, 1);
10693 }
10694
10695 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10696 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10697 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10698 {
10699         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10700                 return;
10701         if (prepass)
10702         {
10703                 // render screenspace normalmap to texture
10704                 GL_DepthMask(true);
10705                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10706                 RSurf_DrawBatch();
10707                 return;
10708         }
10709
10710         // bind lightmap texture
10711
10712         // water/refraction/reflection/camera surfaces have to be handled specially
10713         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10714         {
10715                 int start, end, startplaneindex;
10716                 for (start = 0;start < texturenumsurfaces;start = end)
10717                 {
10718                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10719                         if(startplaneindex < 0)
10720                         {
10721                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10722                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10723                                 end = start + 1;
10724                                 continue;
10725                         }
10726                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10727                                 ;
10728                         // now that we have a batch using the same planeindex, render it
10729                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10730                         {
10731                                 // render water or distortion background
10732                                 GL_DepthMask(true);
10733                                 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);
10734                                 RSurf_DrawBatch();
10735                                 // blend surface on top
10736                                 GL_DepthMask(false);
10737                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10738                                 RSurf_DrawBatch();
10739                         }
10740                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10741                         {
10742                                 // render surface with reflection texture as input
10743                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10744                                 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);
10745                                 RSurf_DrawBatch();
10746                         }
10747                 }
10748                 return;
10749         }
10750
10751         // render surface batch normally
10752         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10753         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);
10754         RSurf_DrawBatch();
10755 }
10756
10757 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10758 {
10759         // OpenGL 1.3 path - anything not completely ancient
10760         qboolean applycolor;
10761         qboolean applyfog;
10762         int layerindex;
10763         const texturelayer_t *layer;
10764         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);
10765         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10766
10767         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10768         {
10769                 vec4_t layercolor;
10770                 int layertexrgbscale;
10771                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10772                 {
10773                         if (layerindex == 0)
10774                                 GL_AlphaTest(true);
10775                         else
10776                         {
10777                                 GL_AlphaTest(false);
10778                                 GL_DepthFunc(GL_EQUAL);
10779                         }
10780                 }
10781                 GL_DepthMask(layer->depthmask && writedepth);
10782                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10783                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10784                 {
10785                         layertexrgbscale = 4;
10786                         VectorScale(layer->color, 0.25f, layercolor);
10787                 }
10788                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10789                 {
10790                         layertexrgbscale = 2;
10791                         VectorScale(layer->color, 0.5f, layercolor);
10792                 }
10793                 else
10794                 {
10795                         layertexrgbscale = 1;
10796                         VectorScale(layer->color, 1.0f, layercolor);
10797                 }
10798                 layercolor[3] = layer->color[3];
10799                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10800                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10801                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10802                 switch (layer->type)
10803                 {
10804                 case TEXTURELAYERTYPE_LITTEXTURE:
10805                         // single-pass lightmapped texture with 2x rgbscale
10806                         R_Mesh_TexBind(0, r_texture_white);
10807                         R_Mesh_TexMatrix(0, NULL);
10808                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10809                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10810                         R_Mesh_TexBind(1, layer->texture);
10811                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10812                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10813                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10814                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10815                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10816                         else if (FAKELIGHT_ENABLED)
10817                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10818                         else if (rsurface.uselightmaptexture)
10819                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10820                         else
10821                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10822                         break;
10823                 case TEXTURELAYERTYPE_TEXTURE:
10824                         // singletexture unlit texture with transparency support
10825                         R_Mesh_TexBind(0, layer->texture);
10826                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10827                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10828                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10829                         R_Mesh_TexBind(1, 0);
10830                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10831                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10832                         break;
10833                 case TEXTURELAYERTYPE_FOG:
10834                         // singletexture fogging
10835                         if (layer->texture)
10836                         {
10837                                 R_Mesh_TexBind(0, layer->texture);
10838                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10839                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10840                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10841                         }
10842                         else
10843                         {
10844                                 R_Mesh_TexBind(0, 0);
10845                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10846                         }
10847                         R_Mesh_TexBind(1, 0);
10848                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10849                         // generate a color array for the fog pass
10850                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10851                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10852                         RSurf_DrawBatch();
10853                         break;
10854                 default:
10855                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10856                 }
10857         }
10858         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10859         {
10860                 GL_DepthFunc(GL_LEQUAL);
10861                 GL_AlphaTest(false);
10862         }
10863 }
10864
10865 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10866 {
10867         // OpenGL 1.1 - crusty old voodoo path
10868         qboolean applyfog;
10869         int layerindex;
10870         const texturelayer_t *layer;
10871         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);
10872         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10873
10874         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10875         {
10876                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10877                 {
10878                         if (layerindex == 0)
10879                                 GL_AlphaTest(true);
10880                         else
10881                         {
10882                                 GL_AlphaTest(false);
10883                                 GL_DepthFunc(GL_EQUAL);
10884                         }
10885                 }
10886                 GL_DepthMask(layer->depthmask && writedepth);
10887                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10888                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10889                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10890                 switch (layer->type)
10891                 {
10892                 case TEXTURELAYERTYPE_LITTEXTURE:
10893                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10894                         {
10895                                 // two-pass lit texture with 2x rgbscale
10896                                 // first the lightmap pass
10897                                 R_Mesh_TexBind(0, r_texture_white);
10898                                 R_Mesh_TexMatrix(0, NULL);
10899                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10900                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10901                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10902                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10903                                 else if (FAKELIGHT_ENABLED)
10904                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10905                                 else if (rsurface.uselightmaptexture)
10906                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10907                                 else
10908                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10909                                 // then apply the texture to it
10910                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10911                                 R_Mesh_TexBind(0, layer->texture);
10912                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10913                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10914                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10915                                 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);
10916                         }
10917                         else
10918                         {
10919                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10920                                 R_Mesh_TexBind(0, layer->texture);
10921                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10922                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10923                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10924                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10925                                         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);
10926                                 else if (FAKELIGHT_ENABLED)
10927                                         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);
10928                                 else
10929                                         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);
10930                         }
10931                         break;
10932                 case TEXTURELAYERTYPE_TEXTURE:
10933                         // singletexture unlit texture with transparency support
10934                         R_Mesh_TexBind(0, layer->texture);
10935                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10936                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10937                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10938                         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);
10939                         break;
10940                 case TEXTURELAYERTYPE_FOG:
10941                         // singletexture fogging
10942                         if (layer->texture)
10943                         {
10944                                 R_Mesh_TexBind(0, layer->texture);
10945                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10946                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10947                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10948                         }
10949                         else
10950                         {
10951                                 R_Mesh_TexBind(0, 0);
10952                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10953                         }
10954                         // generate a color array for the fog pass
10955                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10956                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10957                         RSurf_DrawBatch();
10958                         break;
10959                 default:
10960                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10961                 }
10962         }
10963         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10964         {
10965                 GL_DepthFunc(GL_LEQUAL);
10966                 GL_AlphaTest(false);
10967         }
10968 }
10969
10970 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10971 {
10972         int vi;
10973         int j;
10974         r_vertexgeneric_t *batchvertex;
10975         float c[4];
10976
10977 //      R_Mesh_ResetTextureState();
10978         R_SetupShader_Generic_NoTexture(false, false);
10979
10980         if(rsurface.texture && rsurface.texture->currentskinframe)
10981         {
10982                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10983                 c[3] *= rsurface.texture->currentalpha;
10984         }
10985         else
10986         {
10987                 c[0] = 1;
10988                 c[1] = 0;
10989                 c[2] = 1;
10990                 c[3] = 1;
10991         }
10992
10993         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10994         {
10995                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10996                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10997                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10998         }
10999
11000         // brighten it up (as texture value 127 means "unlit")
11001         c[0] *= 2 * r_refdef.view.colorscale;
11002         c[1] *= 2 * r_refdef.view.colorscale;
11003         c[2] *= 2 * r_refdef.view.colorscale;
11004
11005         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11006                 c[3] *= r_wateralpha.value;
11007
11008         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11009         {
11010                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11011                 GL_DepthMask(false);
11012         }
11013         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11014         {
11015                 GL_BlendFunc(GL_ONE, GL_ONE);
11016                 GL_DepthMask(false);
11017         }
11018         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11019         {
11020                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11021                 GL_DepthMask(false);
11022         }
11023         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11024         {
11025                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11026                 GL_DepthMask(false);
11027         }
11028         else
11029         {
11030                 GL_BlendFunc(GL_ONE, GL_ZERO);
11031                 GL_DepthMask(writedepth);
11032         }
11033
11034         if (r_showsurfaces.integer == 3)
11035         {
11036                 rsurface.passcolor4f = NULL;
11037
11038                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11039                 {
11040                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11041
11042                         rsurface.passcolor4f = NULL;
11043                         rsurface.passcolor4f_vertexbuffer = 0;
11044                         rsurface.passcolor4f_bufferoffset = 0;
11045                 }
11046                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11047                 {
11048                         qboolean applycolor = true;
11049                         float one = 1.0;
11050
11051                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11052
11053                         r_refdef.lightmapintensity = 1;
11054                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11055                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11056                 }
11057                 else if (FAKELIGHT_ENABLED)
11058                 {
11059                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11060
11061                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11062                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11063                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11064                 }
11065                 else
11066                 {
11067                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11068
11069                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11070                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11071                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11072                 }
11073
11074                 if(!rsurface.passcolor4f)
11075                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11076
11077                 RSurf_DrawBatch_GL11_ApplyAmbient();
11078                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11079                 if(r_refdef.fogenabled)
11080                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11081                 RSurf_DrawBatch_GL11_ClampColor();
11082
11083                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11084                 R_SetupShader_Generic_NoTexture(false, false);
11085                 RSurf_DrawBatch();
11086         }
11087         else if (!r_refdef.view.showdebug)
11088         {
11089                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11090                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11091                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11092                 {
11093                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11094                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11095                 }
11096                 R_Mesh_PrepareVertices_Generic_Unlock();
11097                 RSurf_DrawBatch();
11098         }
11099         else if (r_showsurfaces.integer == 4)
11100         {
11101                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11102                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11103                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11104                 {
11105                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11106                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11107                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11108                 }
11109                 R_Mesh_PrepareVertices_Generic_Unlock();
11110                 RSurf_DrawBatch();
11111         }
11112         else if (r_showsurfaces.integer == 2)
11113         {
11114                 const int *e;
11115                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11116                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11117                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11118                 {
11119                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11120                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11121                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11122                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11123                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11124                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11125                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11126                 }
11127                 R_Mesh_PrepareVertices_Generic_Unlock();
11128                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11129         }
11130         else
11131         {
11132                 int texturesurfaceindex;
11133                 int k;
11134                 const msurface_t *surface;
11135                 float surfacecolor4f[4];
11136                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11137                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11138                 vi = 0;
11139                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11140                 {
11141                         surface = texturesurfacelist[texturesurfaceindex];
11142                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11143                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11144                         for (j = 0;j < surface->num_vertices;j++)
11145                         {
11146                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11147                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11148                                 vi++;
11149                         }
11150                 }
11151                 R_Mesh_PrepareVertices_Generic_Unlock();
11152                 RSurf_DrawBatch();
11153         }
11154 }
11155
11156 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11157 {
11158         CHECKGLERROR
11159         RSurf_SetupDepthAndCulling();
11160         if (r_showsurfaces.integer)
11161         {
11162                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11163                 return;
11164         }
11165         switch (vid.renderpath)
11166         {
11167         case RENDERPATH_GL20:
11168         case RENDERPATH_D3D9:
11169         case RENDERPATH_D3D10:
11170         case RENDERPATH_D3D11:
11171         case RENDERPATH_SOFT:
11172         case RENDERPATH_GLES2:
11173                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11174                 break;
11175         case RENDERPATH_GL13:
11176         case RENDERPATH_GLES1:
11177                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11178                 break;
11179         case RENDERPATH_GL11:
11180                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11181                 break;
11182         }
11183         CHECKGLERROR
11184 }
11185
11186 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11187 {
11188         CHECKGLERROR
11189         RSurf_SetupDepthAndCulling();
11190         if (r_showsurfaces.integer)
11191         {
11192                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11193                 return;
11194         }
11195         switch (vid.renderpath)
11196         {
11197         case RENDERPATH_GL20:
11198         case RENDERPATH_D3D9:
11199         case RENDERPATH_D3D10:
11200         case RENDERPATH_D3D11:
11201         case RENDERPATH_SOFT:
11202         case RENDERPATH_GLES2:
11203                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11204                 break;
11205         case RENDERPATH_GL13:
11206         case RENDERPATH_GLES1:
11207                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11208                 break;
11209         case RENDERPATH_GL11:
11210                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11211                 break;
11212         }
11213         CHECKGLERROR
11214 }
11215
11216 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11217 {
11218         int i, j;
11219         int texturenumsurfaces, endsurface;
11220         texture_t *texture;
11221         const msurface_t *surface;
11222         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11223
11224         // if the model is static it doesn't matter what value we give for
11225         // wantnormals and wanttangents, so this logic uses only rules applicable
11226         // to a model, knowing that they are meaningless otherwise
11227         if (ent == r_refdef.scene.worldentity)
11228                 RSurf_ActiveWorldEntity();
11229         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11230                 RSurf_ActiveModelEntity(ent, false, false, false);
11231         else
11232         {
11233                 switch (vid.renderpath)
11234                 {
11235                 case RENDERPATH_GL20:
11236                 case RENDERPATH_D3D9:
11237                 case RENDERPATH_D3D10:
11238                 case RENDERPATH_D3D11:
11239                 case RENDERPATH_SOFT:
11240                 case RENDERPATH_GLES2:
11241                         RSurf_ActiveModelEntity(ent, true, true, false);
11242                         break;
11243                 case RENDERPATH_GL11:
11244                 case RENDERPATH_GL13:
11245                 case RENDERPATH_GLES1:
11246                         RSurf_ActiveModelEntity(ent, true, false, false);
11247                         break;
11248                 }
11249         }
11250
11251         if (r_transparentdepthmasking.integer)
11252         {
11253                 qboolean setup = false;
11254                 for (i = 0;i < numsurfaces;i = j)
11255                 {
11256                         j = i + 1;
11257                         surface = rsurface.modelsurfaces + surfacelist[i];
11258                         texture = surface->texture;
11259                         rsurface.texture = R_GetCurrentTexture(texture);
11260                         rsurface.lightmaptexture = NULL;
11261                         rsurface.deluxemaptexture = NULL;
11262                         rsurface.uselightmaptexture = false;
11263                         // scan ahead until we find a different texture
11264                         endsurface = min(i + 1024, numsurfaces);
11265                         texturenumsurfaces = 0;
11266                         texturesurfacelist[texturenumsurfaces++] = surface;
11267                         for (;j < endsurface;j++)
11268                         {
11269                                 surface = rsurface.modelsurfaces + surfacelist[j];
11270                                 if (texture != surface->texture)
11271                                         break;
11272                                 texturesurfacelist[texturenumsurfaces++] = surface;
11273                         }
11274                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11275                                 continue;
11276                         // render the range of surfaces as depth
11277                         if (!setup)
11278                         {
11279                                 setup = true;
11280                                 GL_ColorMask(0,0,0,0);
11281                                 GL_Color(1,1,1,1);
11282                                 GL_DepthTest(true);
11283                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11284                                 GL_DepthMask(true);
11285 //                              R_Mesh_ResetTextureState();
11286                         }
11287                         RSurf_SetupDepthAndCulling();
11288                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11289                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11290                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11291                         RSurf_DrawBatch();
11292                 }
11293                 if (setup)
11294                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11295         }
11296
11297         for (i = 0;i < numsurfaces;i = j)
11298         {
11299                 j = i + 1;
11300                 surface = rsurface.modelsurfaces + surfacelist[i];
11301                 texture = surface->texture;
11302                 rsurface.texture = R_GetCurrentTexture(texture);
11303                 // scan ahead until we find a different texture
11304                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11305                 texturenumsurfaces = 0;
11306                 texturesurfacelist[texturenumsurfaces++] = surface;
11307                 if(FAKELIGHT_ENABLED)
11308                 {
11309                         rsurface.lightmaptexture = NULL;
11310                         rsurface.deluxemaptexture = NULL;
11311                         rsurface.uselightmaptexture = false;
11312                         for (;j < endsurface;j++)
11313                         {
11314                                 surface = rsurface.modelsurfaces + surfacelist[j];
11315                                 if (texture != surface->texture)
11316                                         break;
11317                                 texturesurfacelist[texturenumsurfaces++] = surface;
11318                         }
11319                 }
11320                 else
11321                 {
11322                         rsurface.lightmaptexture = surface->lightmaptexture;
11323                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11324                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11325                         for (;j < endsurface;j++)
11326                         {
11327                                 surface = rsurface.modelsurfaces + surfacelist[j];
11328                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11329                                         break;
11330                                 texturesurfacelist[texturenumsurfaces++] = surface;
11331                         }
11332                 }
11333                 // render the range of surfaces
11334                 if (ent == r_refdef.scene.worldentity)
11335                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11336                 else
11337                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11338         }
11339         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11340 }
11341
11342 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11343 {
11344         // transparent surfaces get pushed off into the transparent queue
11345         int surfacelistindex;
11346         const msurface_t *surface;
11347         vec3_t tempcenter, center;
11348         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11349         {
11350                 surface = texturesurfacelist[surfacelistindex];
11351                 if (r_transparent_sortsurfacesbynearest.integer)
11352                 {
11353                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11354                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11355                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11356                 }
11357                 else
11358                 {
11359                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11360                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11361                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11362                 }
11363                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11364                 if (rsurface.entity->transparent_offset) // transparent offset
11365                 {
11366                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11367                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11368                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11369                 }
11370                 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);
11371         }
11372 }
11373
11374 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11375 {
11376         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11377                 return;
11378         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11379                 return;
11380         RSurf_SetupDepthAndCulling();
11381         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11382         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11383         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11384         RSurf_DrawBatch();
11385 }
11386
11387 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11388 {
11389         CHECKGLERROR
11390         if (depthonly)
11391                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11392         else if (prepass)
11393         {
11394                 if (!rsurface.texture->currentnumlayers)
11395                         return;
11396                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11397                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11398                 else
11399                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11400         }
11401         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11402                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11403         else if (!rsurface.texture->currentnumlayers)
11404                 return;
11405         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11406         {
11407                 // in the deferred case, transparent surfaces were queued during prepass
11408                 if (!r_shadow_usingdeferredprepass)
11409                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11410         }
11411         else
11412         {
11413                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11414                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11415         }
11416         CHECKGLERROR
11417 }
11418
11419 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11420 {
11421         int i, j;
11422         texture_t *texture;
11423         R_FrameData_SetMark();
11424         // break the surface list down into batches by texture and use of lightmapping
11425         for (i = 0;i < numsurfaces;i = j)
11426         {
11427                 j = i + 1;
11428                 // texture is the base texture pointer, rsurface.texture is the
11429                 // current frame/skin the texture is directing us to use (for example
11430                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11431                 // use skin 1 instead)
11432                 texture = surfacelist[i]->texture;
11433                 rsurface.texture = R_GetCurrentTexture(texture);
11434                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11435                 {
11436                         // if this texture is not the kind we want, skip ahead to the next one
11437                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11438                                 ;
11439                         continue;
11440                 }
11441                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11442                 {
11443                         rsurface.lightmaptexture = NULL;
11444                         rsurface.deluxemaptexture = NULL;
11445                         rsurface.uselightmaptexture = false;
11446                         // simply scan ahead until we find a different texture or lightmap state
11447                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11448                                 ;
11449                 }
11450                 else
11451                 {
11452                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11453                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11454                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11455                         // simply scan ahead until we find a different texture or lightmap state
11456                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11457                                 ;
11458                 }
11459                 // render the range of surfaces
11460                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11461         }
11462         R_FrameData_ReturnToMark();
11463 }
11464
11465 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11466 {
11467         CHECKGLERROR
11468         if (depthonly)
11469                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11470         else if (prepass)
11471         {
11472                 if (!rsurface.texture->currentnumlayers)
11473                         return;
11474                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11475                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11476                 else
11477                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11478         }
11479         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11480                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11481         else if (!rsurface.texture->currentnumlayers)
11482                 return;
11483         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11484         {
11485                 // in the deferred case, transparent surfaces were queued during prepass
11486                 if (!r_shadow_usingdeferredprepass)
11487                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11488         }
11489         else
11490         {
11491                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11492                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11493         }
11494         CHECKGLERROR
11495 }
11496
11497 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11498 {
11499         int i, j;
11500         texture_t *texture;
11501         R_FrameData_SetMark();
11502         // break the surface list down into batches by texture and use of lightmapping
11503         for (i = 0;i < numsurfaces;i = j)
11504         {
11505                 j = i + 1;
11506                 // texture is the base texture pointer, rsurface.texture is the
11507                 // current frame/skin the texture is directing us to use (for example
11508                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11509                 // use skin 1 instead)
11510                 texture = surfacelist[i]->texture;
11511                 rsurface.texture = R_GetCurrentTexture(texture);
11512                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11513                 {
11514                         // if this texture is not the kind we want, skip ahead to the next one
11515                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11516                                 ;
11517                         continue;
11518                 }
11519                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11520                 {
11521                         rsurface.lightmaptexture = NULL;
11522                         rsurface.deluxemaptexture = NULL;
11523                         rsurface.uselightmaptexture = false;
11524                         // simply scan ahead until we find a different texture or lightmap state
11525                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11526                                 ;
11527                 }
11528                 else
11529                 {
11530                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11531                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11532                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11533                         // simply scan ahead until we find a different texture or lightmap state
11534                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11535                                 ;
11536                 }
11537                 // render the range of surfaces
11538                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11539         }
11540         R_FrameData_ReturnToMark();
11541 }
11542
11543 float locboxvertex3f[6*4*3] =
11544 {
11545         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11546         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11547         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11548         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11549         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11550         1,0,0, 0,0,0, 0,1,0, 1,1,0
11551 };
11552
11553 unsigned short locboxelements[6*2*3] =
11554 {
11555          0, 1, 2, 0, 2, 3,
11556          4, 5, 6, 4, 6, 7,
11557          8, 9,10, 8,10,11,
11558         12,13,14, 12,14,15,
11559         16,17,18, 16,18,19,
11560         20,21,22, 20,22,23
11561 };
11562
11563 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11564 {
11565         int i, j;
11566         cl_locnode_t *loc = (cl_locnode_t *)ent;
11567         vec3_t mins, size;
11568         float vertex3f[6*4*3];
11569         CHECKGLERROR
11570         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11571         GL_DepthMask(false);
11572         GL_DepthRange(0, 1);
11573         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11574         GL_DepthTest(true);
11575         GL_CullFace(GL_NONE);
11576         R_EntityMatrix(&identitymatrix);
11577
11578 //      R_Mesh_ResetTextureState();
11579
11580         i = surfacelist[0];
11581         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11582                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11583                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11584                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11585
11586         if (VectorCompare(loc->mins, loc->maxs))
11587         {
11588                 VectorSet(size, 2, 2, 2);
11589                 VectorMA(loc->mins, -0.5f, size, mins);
11590         }
11591         else
11592         {
11593                 VectorCopy(loc->mins, mins);
11594                 VectorSubtract(loc->maxs, loc->mins, size);
11595         }
11596
11597         for (i = 0;i < 6*4*3;)
11598                 for (j = 0;j < 3;j++, i++)
11599                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11600
11601         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11602         R_SetupShader_Generic_NoTexture(false, false);
11603         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11604 }
11605
11606 void R_DrawLocs(void)
11607 {
11608         int index;
11609         cl_locnode_t *loc, *nearestloc;
11610         vec3_t center;
11611         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11612         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11613         {
11614                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11615                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11616         }
11617 }
11618
11619 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11620 {
11621         if (decalsystem->decals)
11622                 Mem_Free(decalsystem->decals);
11623         memset(decalsystem, 0, sizeof(*decalsystem));
11624 }
11625
11626 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, int decalsequence)
11627 {
11628         tridecal_t *decal;
11629         tridecal_t *decals;
11630         int i;
11631
11632         // expand or initialize the system
11633         if (decalsystem->maxdecals <= decalsystem->numdecals)
11634         {
11635                 decalsystem_t old = *decalsystem;
11636                 qboolean useshortelements;
11637                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11638                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11639                 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)));
11640                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11641                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11642                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11643                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11644                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11645                 if (decalsystem->numdecals)
11646                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11647                 if (old.decals)
11648                         Mem_Free(old.decals);
11649                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11650                         decalsystem->element3i[i] = i;
11651                 if (useshortelements)
11652                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11653                                 decalsystem->element3s[i] = i;
11654         }
11655
11656         // grab a decal and search for another free slot for the next one
11657         decals = decalsystem->decals;
11658         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11659         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11660                 ;
11661         decalsystem->freedecal = i;
11662         if (decalsystem->numdecals <= i)
11663                 decalsystem->numdecals = i + 1;
11664
11665         // initialize the decal
11666         decal->lived = 0;
11667         decal->triangleindex = triangleindex;
11668         decal->surfaceindex = surfaceindex;
11669         decal->decalsequence = decalsequence;
11670         decal->color4f[0][0] = c0[0];
11671         decal->color4f[0][1] = c0[1];
11672         decal->color4f[0][2] = c0[2];
11673         decal->color4f[0][3] = 1;
11674         decal->color4f[1][0] = c1[0];
11675         decal->color4f[1][1] = c1[1];
11676         decal->color4f[1][2] = c1[2];
11677         decal->color4f[1][3] = 1;
11678         decal->color4f[2][0] = c2[0];
11679         decal->color4f[2][1] = c2[1];
11680         decal->color4f[2][2] = c2[2];
11681         decal->color4f[2][3] = 1;
11682         decal->vertex3f[0][0] = v0[0];
11683         decal->vertex3f[0][1] = v0[1];
11684         decal->vertex3f[0][2] = v0[2];
11685         decal->vertex3f[1][0] = v1[0];
11686         decal->vertex3f[1][1] = v1[1];
11687         decal->vertex3f[1][2] = v1[2];
11688         decal->vertex3f[2][0] = v2[0];
11689         decal->vertex3f[2][1] = v2[1];
11690         decal->vertex3f[2][2] = v2[2];
11691         decal->texcoord2f[0][0] = t0[0];
11692         decal->texcoord2f[0][1] = t0[1];
11693         decal->texcoord2f[1][0] = t1[0];
11694         decal->texcoord2f[1][1] = t1[1];
11695         decal->texcoord2f[2][0] = t2[0];
11696         decal->texcoord2f[2][1] = t2[1];
11697         TriangleNormal(v0, v1, v2, decal->plane);
11698         VectorNormalize(decal->plane);
11699         decal->plane[3] = DotProduct(v0, decal->plane);
11700 }
11701
11702 extern cvar_t cl_decals_bias;
11703 extern cvar_t cl_decals_models;
11704 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11705 // baseparms, parms, temps
11706 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11707 {
11708         int cornerindex;
11709         int index;
11710         float v[9][3];
11711         const float *vertex3f;
11712         const float *normal3f;
11713         int numpoints;
11714         float points[2][9][3];
11715         float temp[3];
11716         float tc[9][2];
11717         float f;
11718         float c[9][4];
11719         const int *e;
11720
11721         e = rsurface.modelelement3i + 3*triangleindex;
11722
11723         vertex3f = rsurface.modelvertex3f;
11724         normal3f = rsurface.modelnormal3f;
11725
11726         if (normal3f)
11727         {
11728                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11729                 {
11730                         index = 3*e[cornerindex];
11731                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11732                 }
11733         }
11734         else
11735         {
11736                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11737                 {
11738                         index = 3*e[cornerindex];
11739                         VectorCopy(vertex3f + index, v[cornerindex]);
11740                 }
11741         }
11742
11743         // cull backfaces
11744         //TriangleNormal(v[0], v[1], v[2], normal);
11745         //if (DotProduct(normal, localnormal) < 0.0f)
11746         //      continue;
11747         // clip by each of the box planes formed from the projection matrix
11748         // if anything survives, we emit the decal
11749         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]);
11750         if (numpoints < 3)
11751                 return;
11752         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]);
11753         if (numpoints < 3)
11754                 return;
11755         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]);
11756         if (numpoints < 3)
11757                 return;
11758         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]);
11759         if (numpoints < 3)
11760                 return;
11761         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]);
11762         if (numpoints < 3)
11763                 return;
11764         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]);
11765         if (numpoints < 3)
11766                 return;
11767         // some part of the triangle survived, so we have to accept it...
11768         if (dynamic)
11769         {
11770                 // dynamic always uses the original triangle
11771                 numpoints = 3;
11772                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11773                 {
11774                         index = 3*e[cornerindex];
11775                         VectorCopy(vertex3f + index, v[cornerindex]);
11776                 }
11777         }
11778         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11779         {
11780                 // convert vertex positions to texcoords
11781                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11782                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11783                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11784                 // calculate distance fade from the projection origin
11785                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11786                 f = bound(0.0f, f, 1.0f);
11787                 c[cornerindex][0] = r * f;
11788                 c[cornerindex][1] = g * f;
11789                 c[cornerindex][2] = b * f;
11790                 c[cornerindex][3] = 1.0f;
11791                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11792         }
11793         if (dynamic)
11794                 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);
11795         else
11796                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11797                         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);
11798 }
11799 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, int decalsequence)
11800 {
11801         matrix4x4_t projection;
11802         decalsystem_t *decalsystem;
11803         qboolean dynamic;
11804         dp_model_t *model;
11805         const msurface_t *surface;
11806         const msurface_t *surfaces;
11807         const int *surfacelist;
11808         const texture_t *texture;
11809         int numtriangles;
11810         int numsurfacelist;
11811         int surfacelistindex;
11812         int surfaceindex;
11813         int triangleindex;
11814         float localorigin[3];
11815         float localnormal[3];
11816         float localmins[3];
11817         float localmaxs[3];
11818         float localsize;
11819         //float normal[3];
11820         float planes[6][4];
11821         float angles[3];
11822         bih_t *bih;
11823         int bih_triangles_count;
11824         int bih_triangles[256];
11825         int bih_surfaces[256];
11826
11827         decalsystem = &ent->decalsystem;
11828         model = ent->model;
11829         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11830         {
11831                 R_DecalSystem_Reset(&ent->decalsystem);
11832                 return;
11833         }
11834
11835         if (!model->brush.data_leafs && !cl_decals_models.integer)
11836         {
11837                 if (decalsystem->model)
11838                         R_DecalSystem_Reset(decalsystem);
11839                 return;
11840         }
11841
11842         if (decalsystem->model != model)
11843                 R_DecalSystem_Reset(decalsystem);
11844         decalsystem->model = model;
11845
11846         RSurf_ActiveModelEntity(ent, true, false, false);
11847
11848         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11849         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11850         VectorNormalize(localnormal);
11851         localsize = worldsize*rsurface.inversematrixscale;
11852         localmins[0] = localorigin[0] - localsize;
11853         localmins[1] = localorigin[1] - localsize;
11854         localmins[2] = localorigin[2] - localsize;
11855         localmaxs[0] = localorigin[0] + localsize;
11856         localmaxs[1] = localorigin[1] + localsize;
11857         localmaxs[2] = localorigin[2] + localsize;
11858
11859         //VectorCopy(localnormal, planes[4]);
11860         //VectorVectors(planes[4], planes[2], planes[0]);
11861         AnglesFromVectors(angles, localnormal, NULL, false);
11862         AngleVectors(angles, planes[0], planes[2], planes[4]);
11863         VectorNegate(planes[0], planes[1]);
11864         VectorNegate(planes[2], planes[3]);
11865         VectorNegate(planes[4], planes[5]);
11866         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11867         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11868         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11869         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11870         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11871         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11872
11873 #if 1
11874 // works
11875 {
11876         matrix4x4_t forwardprojection;
11877         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11878         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11879 }
11880 #else
11881 // broken
11882 {
11883         float projectionvector[4][3];
11884         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11885         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11886         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11887         projectionvector[0][0] = planes[0][0] * ilocalsize;
11888         projectionvector[0][1] = planes[1][0] * ilocalsize;
11889         projectionvector[0][2] = planes[2][0] * ilocalsize;
11890         projectionvector[1][0] = planes[0][1] * ilocalsize;
11891         projectionvector[1][1] = planes[1][1] * ilocalsize;
11892         projectionvector[1][2] = planes[2][1] * ilocalsize;
11893         projectionvector[2][0] = planes[0][2] * ilocalsize;
11894         projectionvector[2][1] = planes[1][2] * ilocalsize;
11895         projectionvector[2][2] = planes[2][2] * ilocalsize;
11896         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11897         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11898         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11899         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11900 }
11901 #endif
11902
11903         dynamic = model->surfmesh.isanimated;
11904         numsurfacelist = model->nummodelsurfaces;
11905         surfacelist = model->sortedmodelsurfaces;
11906         surfaces = model->data_surfaces;
11907
11908         bih = NULL;
11909         bih_triangles_count = -1;
11910         if(!dynamic)
11911         {
11912                 if(model->render_bih.numleafs)
11913                         bih = &model->render_bih;
11914                 else if(model->collision_bih.numleafs)
11915                         bih = &model->collision_bih;
11916         }
11917         if(bih)
11918                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11919         if(bih_triangles_count == 0)
11920                 return;
11921         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11922                 return;
11923         if(bih_triangles_count > 0)
11924         {
11925                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11926                 {
11927                         surfaceindex = bih_surfaces[triangleindex];
11928                         surface = surfaces + surfaceindex;
11929                         texture = surface->texture;
11930                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11931                                 continue;
11932                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11933                                 continue;
11934                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11935                 }
11936         }
11937         else
11938         {
11939                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11940                 {
11941                         surfaceindex = surfacelist[surfacelistindex];
11942                         surface = surfaces + surfaceindex;
11943                         // check cull box first because it rejects more than any other check
11944                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11945                                 continue;
11946                         // skip transparent surfaces
11947                         texture = surface->texture;
11948                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11949                                 continue;
11950                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11951                                 continue;
11952                         numtriangles = surface->num_triangles;
11953                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11954                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11955                 }
11956         }
11957 }
11958
11959 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11960 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, int decalsequence)
11961 {
11962         int renderentityindex;
11963         float worldmins[3];
11964         float worldmaxs[3];
11965         entity_render_t *ent;
11966
11967         if (!cl_decals_newsystem.integer)
11968                 return;
11969
11970         worldmins[0] = worldorigin[0] - worldsize;
11971         worldmins[1] = worldorigin[1] - worldsize;
11972         worldmins[2] = worldorigin[2] - worldsize;
11973         worldmaxs[0] = worldorigin[0] + worldsize;
11974         worldmaxs[1] = worldorigin[1] + worldsize;
11975         worldmaxs[2] = worldorigin[2] + worldsize;
11976
11977         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11978
11979         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11980         {
11981                 ent = r_refdef.scene.entities[renderentityindex];
11982                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11983                         continue;
11984
11985                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11986         }
11987 }
11988
11989 typedef struct r_decalsystem_splatqueue_s
11990 {
11991         vec3_t worldorigin;
11992         vec3_t worldnormal;
11993         float color[4];
11994         float tcrange[4];
11995         float worldsize;
11996         int decalsequence;
11997 }
11998 r_decalsystem_splatqueue_t;
11999
12000 int r_decalsystem_numqueued = 0;
12001 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12002
12003 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)
12004 {
12005         r_decalsystem_splatqueue_t *queue;
12006
12007         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12008                 return;
12009
12010         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12011         VectorCopy(worldorigin, queue->worldorigin);
12012         VectorCopy(worldnormal, queue->worldnormal);
12013         Vector4Set(queue->color, r, g, b, a);
12014         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12015         queue->worldsize = worldsize;
12016         queue->decalsequence = cl.decalsequence++;
12017 }
12018
12019 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12020 {
12021         int i;
12022         r_decalsystem_splatqueue_t *queue;
12023
12024         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12025                 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);
12026         r_decalsystem_numqueued = 0;
12027 }
12028
12029 extern cvar_t cl_decals_max;
12030 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12031 {
12032         int i;
12033         decalsystem_t *decalsystem = &ent->decalsystem;
12034         int numdecals;
12035         int killsequence;
12036         tridecal_t *decal;
12037         float frametime;
12038         float lifetime;
12039
12040         if (!decalsystem->numdecals)
12041                 return;
12042
12043         if (r_showsurfaces.integer)
12044                 return;
12045
12046         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12047         {
12048                 R_DecalSystem_Reset(decalsystem);
12049                 return;
12050         }
12051
12052         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12053         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12054
12055         if (decalsystem->lastupdatetime)
12056                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12057         else
12058                 frametime = 0;
12059         decalsystem->lastupdatetime = r_refdef.scene.time;
12060         numdecals = decalsystem->numdecals;
12061
12062         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12063         {
12064                 if (decal->color4f[0][3])
12065                 {
12066                         decal->lived += frametime;
12067                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12068                         {
12069                                 memset(decal, 0, sizeof(*decal));
12070                                 if (decalsystem->freedecal > i)
12071                                         decalsystem->freedecal = i;
12072                         }
12073                 }
12074         }
12075         decal = decalsystem->decals;
12076         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12077                 numdecals--;
12078
12079         // collapse the array by shuffling the tail decals into the gaps
12080         for (;;)
12081         {
12082                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12083                         decalsystem->freedecal++;
12084                 if (decalsystem->freedecal == numdecals)
12085                         break;
12086                 decal[decalsystem->freedecal] = decal[--numdecals];
12087         }
12088
12089         decalsystem->numdecals = numdecals;
12090
12091         if (numdecals <= 0)
12092         {
12093                 // if there are no decals left, reset decalsystem
12094                 R_DecalSystem_Reset(decalsystem);
12095         }
12096 }
12097
12098 extern skinframe_t *decalskinframe;
12099 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12100 {
12101         int i;
12102         decalsystem_t *decalsystem = &ent->decalsystem;
12103         int numdecals;
12104         tridecal_t *decal;
12105         float faderate;
12106         float alpha;
12107         float *v3f;
12108         float *c4f;
12109         float *t2f;
12110         const int *e;
12111         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12112         int numtris = 0;
12113
12114         numdecals = decalsystem->numdecals;
12115         if (!numdecals)
12116                 return;
12117
12118         if (r_showsurfaces.integer)
12119                 return;
12120
12121         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12122         {
12123                 R_DecalSystem_Reset(decalsystem);
12124                 return;
12125         }
12126
12127         // if the model is static it doesn't matter what value we give for
12128         // wantnormals and wanttangents, so this logic uses only rules applicable
12129         // to a model, knowing that they are meaningless otherwise
12130         if (ent == r_refdef.scene.worldentity)
12131                 RSurf_ActiveWorldEntity();
12132         else
12133                 RSurf_ActiveModelEntity(ent, false, false, false);
12134
12135         decalsystem->lastupdatetime = r_refdef.scene.time;
12136
12137         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12138
12139         // update vertex positions for animated models
12140         v3f = decalsystem->vertex3f;
12141         c4f = decalsystem->color4f;
12142         t2f = decalsystem->texcoord2f;
12143         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12144         {
12145                 if (!decal->color4f[0][3])
12146                         continue;
12147
12148                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12149                         continue;
12150
12151                 // skip backfaces
12152                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12153                         continue;
12154
12155                 // update color values for fading decals
12156                 if (decal->lived >= cl_decals_time.value)
12157                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12158                 else
12159                         alpha = 1.0f;
12160
12161                 c4f[ 0] = decal->color4f[0][0] * alpha;
12162                 c4f[ 1] = decal->color4f[0][1] * alpha;
12163                 c4f[ 2] = decal->color4f[0][2] * alpha;
12164                 c4f[ 3] = 1;
12165                 c4f[ 4] = decal->color4f[1][0] * alpha;
12166                 c4f[ 5] = decal->color4f[1][1] * alpha;
12167                 c4f[ 6] = decal->color4f[1][2] * alpha;
12168                 c4f[ 7] = 1;
12169                 c4f[ 8] = decal->color4f[2][0] * alpha;
12170                 c4f[ 9] = decal->color4f[2][1] * alpha;
12171                 c4f[10] = decal->color4f[2][2] * alpha;
12172                 c4f[11] = 1;
12173
12174                 t2f[0] = decal->texcoord2f[0][0];
12175                 t2f[1] = decal->texcoord2f[0][1];
12176                 t2f[2] = decal->texcoord2f[1][0];
12177                 t2f[3] = decal->texcoord2f[1][1];
12178                 t2f[4] = decal->texcoord2f[2][0];
12179                 t2f[5] = decal->texcoord2f[2][1];
12180
12181                 // update vertex positions for animated models
12182                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12183                 {
12184                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12185                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12186                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12187                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12188                 }
12189                 else
12190                 {
12191                         VectorCopy(decal->vertex3f[0], v3f);
12192                         VectorCopy(decal->vertex3f[1], v3f + 3);
12193                         VectorCopy(decal->vertex3f[2], v3f + 6);
12194                 }
12195
12196                 if (r_refdef.fogenabled)
12197                 {
12198                         alpha = RSurf_FogVertex(v3f);
12199                         VectorScale(c4f, alpha, c4f);
12200                         alpha = RSurf_FogVertex(v3f + 3);
12201                         VectorScale(c4f + 4, alpha, c4f + 4);
12202                         alpha = RSurf_FogVertex(v3f + 6);
12203                         VectorScale(c4f + 8, alpha, c4f + 8);
12204                 }
12205
12206                 v3f += 9;
12207                 c4f += 12;
12208                 t2f += 6;
12209                 numtris++;
12210         }
12211
12212         if (numtris > 0)
12213         {
12214                 r_refdef.stats[r_stat_drawndecals] += numtris;
12215
12216                 // now render the decals all at once
12217                 // (this assumes they all use one particle font texture!)
12218                 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);
12219 //              R_Mesh_ResetTextureState();
12220                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12221                 GL_DepthMask(false);
12222                 GL_DepthRange(0, 1);
12223                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12224                 GL_DepthTest(true);
12225                 GL_CullFace(GL_NONE);
12226                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12227                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12228                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12229         }
12230 }
12231
12232 static void R_DrawModelDecals(void)
12233 {
12234         int i, numdecals;
12235
12236         // fade faster when there are too many decals
12237         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12238         for (i = 0;i < r_refdef.scene.numentities;i++)
12239                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12240
12241         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12242         for (i = 0;i < r_refdef.scene.numentities;i++)
12243                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12244                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12245
12246         R_DecalSystem_ApplySplatEntitiesQueue();
12247
12248         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12249         for (i = 0;i < r_refdef.scene.numentities;i++)
12250                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12251
12252         r_refdef.stats[r_stat_totaldecals] += numdecals;
12253
12254         if (r_showsurfaces.integer)
12255                 return;
12256
12257         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12258
12259         for (i = 0;i < r_refdef.scene.numentities;i++)
12260         {
12261                 if (!r_refdef.viewcache.entityvisible[i])
12262                         continue;
12263                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12264                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12265         }
12266 }
12267
12268 extern cvar_t mod_collision_bih;
12269 static void R_DrawDebugModel(void)
12270 {
12271         entity_render_t *ent = rsurface.entity;
12272         int i, j, flagsmask;
12273         const msurface_t *surface;
12274         dp_model_t *model = ent->model;
12275
12276         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12277                 return;
12278
12279         if (r_showoverdraw.value > 0)
12280         {
12281                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12282                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12283                 R_SetupShader_Generic_NoTexture(false, false);
12284                 GL_DepthTest(false);
12285                 GL_DepthMask(false);
12286                 GL_DepthRange(0, 1);
12287                 GL_BlendFunc(GL_ONE, GL_ONE);
12288                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12289                 {
12290                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12291                                 continue;
12292                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12293                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12294                         {
12295                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12296                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12297                                 if (!rsurface.texture->currentlayers->depthmask)
12298                                         GL_Color(c, 0, 0, 1.0f);
12299                                 else if (ent == r_refdef.scene.worldentity)
12300                                         GL_Color(c, c, c, 1.0f);
12301                                 else
12302                                         GL_Color(0, c, 0, 1.0f);
12303                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12304                                 RSurf_DrawBatch();
12305                         }
12306                 }
12307                 rsurface.texture = NULL;
12308         }
12309
12310         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12311
12312 //      R_Mesh_ResetTextureState();
12313         R_SetupShader_Generic_NoTexture(false, false);
12314         GL_DepthRange(0, 1);
12315         GL_DepthTest(!r_showdisabledepthtest.integer);
12316         GL_DepthMask(false);
12317         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12318
12319         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12320         {
12321                 int triangleindex;
12322                 int bihleafindex;
12323                 qboolean cullbox = false;
12324                 const q3mbrush_t *brush;
12325                 const bih_t *bih = &model->collision_bih;
12326                 const bih_leaf_t *bihleaf;
12327                 float vertex3f[3][3];
12328                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12329                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12330                 {
12331                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12332                                 continue;
12333                         switch (bihleaf->type)
12334                         {
12335                         case BIH_BRUSH:
12336                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12337                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12338                                 {
12339                                         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);
12340                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12341                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12342                                 }
12343                                 break;
12344                         case BIH_COLLISIONTRIANGLE:
12345                                 triangleindex = bihleaf->itemindex;
12346                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12347                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12348                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12349                                 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);
12350                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12351                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12352                                 break;
12353                         case BIH_RENDERTRIANGLE:
12354                                 triangleindex = bihleaf->itemindex;
12355                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12356                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12357                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12358                                 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);
12359                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12360                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12361                                 break;
12362                         }
12363                 }
12364         }
12365
12366         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12367
12368 #ifndef USE_GLES2
12369         if (r_showtris.integer && qglPolygonMode)
12370         {
12371                 if (r_showdisabledepthtest.integer)
12372                 {
12373                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12374                         GL_DepthMask(false);
12375                 }
12376                 else
12377                 {
12378                         GL_BlendFunc(GL_ONE, GL_ZERO);
12379                         GL_DepthMask(true);
12380                 }
12381                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12382                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12383                 {
12384                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12385                                 continue;
12386                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12387                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12388                         {
12389                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12390                                 if (!rsurface.texture->currentlayers->depthmask)
12391                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12392                                 else if (ent == r_refdef.scene.worldentity)
12393                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12394                                 else
12395                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12396                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12397                                 RSurf_DrawBatch();
12398                         }
12399                 }
12400                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12401                 rsurface.texture = NULL;
12402         }
12403
12404         if (r_shownormals.value != 0 && qglBegin)
12405         {
12406                 int l, k;
12407                 vec3_t v;
12408                 if (r_showdisabledepthtest.integer)
12409                 {
12410                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12411                         GL_DepthMask(false);
12412                 }
12413                 else
12414                 {
12415                         GL_BlendFunc(GL_ONE, GL_ZERO);
12416                         GL_DepthMask(true);
12417                 }
12418                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12419                 {
12420                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12421                                 continue;
12422                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12423                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12424                         {
12425                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12426                                 qglBegin(GL_LINES);
12427                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12428                                 {
12429                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12430                                         {
12431                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12432                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12433                                                 qglVertex3f(v[0], v[1], v[2]);
12434                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12435                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12436                                                 qglVertex3f(v[0], v[1], v[2]);
12437                                         }
12438                                 }
12439                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12440                                 {
12441                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12442                                         {
12443                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12444                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12445                                                 qglVertex3f(v[0], v[1], v[2]);
12446                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12447                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12448                                                 qglVertex3f(v[0], v[1], v[2]);
12449                                         }
12450                                 }
12451                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12452                                 {
12453                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12454                                         {
12455                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12456                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12457                                                 qglVertex3f(v[0], v[1], v[2]);
12458                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12459                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12460                                                 qglVertex3f(v[0], v[1], v[2]);
12461                                         }
12462                                 }
12463                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12464                                 {
12465                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12466                                         {
12467                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12468                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12469                                                 qglVertex3f(v[0], v[1], v[2]);
12470                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12471                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12472                                                 qglVertex3f(v[0], v[1], v[2]);
12473                                         }
12474                                 }
12475                                 qglEnd();
12476                                 CHECKGLERROR
12477                         }
12478                 }
12479                 rsurface.texture = NULL;
12480         }
12481 #endif
12482 }
12483
12484 int r_maxsurfacelist = 0;
12485 const msurface_t **r_surfacelist = NULL;
12486 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12487 {
12488         int i, j, endj, flagsmask;
12489         dp_model_t *model = r_refdef.scene.worldmodel;
12490         msurface_t *surfaces;
12491         unsigned char *update;
12492         int numsurfacelist = 0;
12493         if (model == NULL)
12494                 return;
12495
12496         if (r_maxsurfacelist < model->num_surfaces)
12497         {
12498                 r_maxsurfacelist = model->num_surfaces;
12499                 if (r_surfacelist)
12500                         Mem_Free((msurface_t**)r_surfacelist);
12501                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12502         }
12503
12504         RSurf_ActiveWorldEntity();
12505
12506         surfaces = model->data_surfaces;
12507         update = model->brushq1.lightmapupdateflags;
12508
12509         // update light styles on this submodel
12510         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12511         {
12512                 model_brush_lightstyleinfo_t *style;
12513                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12514                 {
12515                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12516                         {
12517                                 int *list = style->surfacelist;
12518                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12519                                 for (j = 0;j < style->numsurfaces;j++)
12520                                         update[list[j]] = true;
12521                         }
12522                 }
12523         }
12524
12525         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12526
12527         if (debug)
12528         {
12529                 R_DrawDebugModel();
12530                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12531                 return;
12532         }
12533
12534         rsurface.lightmaptexture = NULL;
12535         rsurface.deluxemaptexture = NULL;
12536         rsurface.uselightmaptexture = false;
12537         rsurface.texture = NULL;
12538         rsurface.rtlight = NULL;
12539         numsurfacelist = 0;
12540         // add visible surfaces to draw list
12541         for (i = 0;i < model->nummodelsurfaces;i++)
12542         {
12543                 j = model->sortedmodelsurfaces[i];
12544                 if (r_refdef.viewcache.world_surfacevisible[j])
12545                         r_surfacelist[numsurfacelist++] = surfaces + j;
12546         }
12547         // update lightmaps if needed
12548         if (model->brushq1.firstrender)
12549         {
12550                 model->brushq1.firstrender = false;
12551                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12552                         if (update[j])
12553                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12554         }
12555         else if (update)
12556         {
12557                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12558                         if (r_refdef.viewcache.world_surfacevisible[j])
12559                                 if (update[j])
12560                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12561         }
12562         // don't do anything if there were no surfaces
12563         if (!numsurfacelist)
12564         {
12565                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12566                 return;
12567         }
12568         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12569
12570         // add to stats if desired
12571         if (r_speeds.integer && !skysurfaces && !depthonly)
12572         {
12573                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12574                 for (j = 0;j < numsurfacelist;j++)
12575                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12576         }
12577
12578         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12579 }
12580
12581 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12582 {
12583         int i, j, endj, flagsmask;
12584         dp_model_t *model = ent->model;
12585         msurface_t *surfaces;
12586         unsigned char *update;
12587         int numsurfacelist = 0;
12588         if (model == NULL)
12589                 return;
12590
12591         if (r_maxsurfacelist < model->num_surfaces)
12592         {
12593                 r_maxsurfacelist = model->num_surfaces;
12594                 if (r_surfacelist)
12595                         Mem_Free((msurface_t **)r_surfacelist);
12596                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12597         }
12598
12599         // if the model is static it doesn't matter what value we give for
12600         // wantnormals and wanttangents, so this logic uses only rules applicable
12601         // to a model, knowing that they are meaningless otherwise
12602         if (ent == r_refdef.scene.worldentity)
12603                 RSurf_ActiveWorldEntity();
12604         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12605                 RSurf_ActiveModelEntity(ent, false, false, false);
12606         else if (prepass)
12607                 RSurf_ActiveModelEntity(ent, true, true, true);
12608         else if (depthonly)
12609         {
12610                 switch (vid.renderpath)
12611                 {
12612                 case RENDERPATH_GL20:
12613                 case RENDERPATH_D3D9:
12614                 case RENDERPATH_D3D10:
12615                 case RENDERPATH_D3D11:
12616                 case RENDERPATH_SOFT:
12617                 case RENDERPATH_GLES2:
12618                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12619                         break;
12620                 case RENDERPATH_GL11:
12621                 case RENDERPATH_GL13:
12622                 case RENDERPATH_GLES1:
12623                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12624                         break;
12625                 }
12626         }
12627         else
12628         {
12629                 switch (vid.renderpath)
12630                 {
12631                 case RENDERPATH_GL20:
12632                 case RENDERPATH_D3D9:
12633                 case RENDERPATH_D3D10:
12634                 case RENDERPATH_D3D11:
12635                 case RENDERPATH_SOFT:
12636                 case RENDERPATH_GLES2:
12637                         RSurf_ActiveModelEntity(ent, true, true, false);
12638                         break;
12639                 case RENDERPATH_GL11:
12640                 case RENDERPATH_GL13:
12641                 case RENDERPATH_GLES1:
12642                         RSurf_ActiveModelEntity(ent, true, false, false);
12643                         break;
12644                 }
12645         }
12646
12647         surfaces = model->data_surfaces;
12648         update = model->brushq1.lightmapupdateflags;
12649
12650         // update light styles
12651         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12652         {
12653                 model_brush_lightstyleinfo_t *style;
12654                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12655                 {
12656                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12657                         {
12658                                 int *list = style->surfacelist;
12659                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12660                                 for (j = 0;j < style->numsurfaces;j++)
12661                                         update[list[j]] = true;
12662                         }
12663                 }
12664         }
12665
12666         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12667
12668         if (debug)
12669         {
12670                 R_DrawDebugModel();
12671                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12672                 return;
12673         }
12674
12675         rsurface.lightmaptexture = NULL;
12676         rsurface.deluxemaptexture = NULL;
12677         rsurface.uselightmaptexture = false;
12678         rsurface.texture = NULL;
12679         rsurface.rtlight = NULL;
12680         numsurfacelist = 0;
12681         // add visible surfaces to draw list
12682         for (i = 0;i < model->nummodelsurfaces;i++)
12683                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12684         // don't do anything if there were no surfaces
12685         if (!numsurfacelist)
12686         {
12687                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12688                 return;
12689         }
12690         // update lightmaps if needed
12691         if (update)
12692         {
12693                 int updated = 0;
12694                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12695                 {
12696                         if (update[j])
12697                         {
12698                                 updated++;
12699                                 R_BuildLightMap(ent, surfaces + j);
12700                         }
12701                 }
12702         }
12703
12704         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12705
12706         // add to stats if desired
12707         if (r_speeds.integer && !skysurfaces && !depthonly)
12708         {
12709                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12710                 for (j = 0;j < numsurfacelist;j++)
12711                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12712         }
12713
12714         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12715 }
12716
12717 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12718 {
12719         static texture_t texture;
12720         static msurface_t surface;
12721         const msurface_t *surfacelist = &surface;
12722
12723         // fake enough texture and surface state to render this geometry
12724
12725         texture.update_lastrenderframe = -1; // regenerate this texture
12726         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12727         texture.basealpha = 1.0f;
12728         texture.currentskinframe = skinframe;
12729         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12730         texture.offsetmapping = OFFSETMAPPING_OFF;
12731         texture.offsetscale = 1;
12732         texture.specularscalemod = 1;
12733         texture.specularpowermod = 1;
12734         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12735         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12736         // JUST GREP FOR "specularscalemod = 1".
12737
12738         surface.texture = &texture;
12739         surface.num_triangles = numtriangles;
12740         surface.num_firsttriangle = firsttriangle;
12741         surface.num_vertices = numvertices;
12742         surface.num_firstvertex = firstvertex;
12743
12744         // now render it
12745         rsurface.texture = R_GetCurrentTexture(surface.texture);
12746         rsurface.lightmaptexture = NULL;
12747         rsurface.deluxemaptexture = NULL;
12748         rsurface.uselightmaptexture = false;
12749         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12750 }
12751
12752 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)
12753 {
12754         static msurface_t surface;
12755         const msurface_t *surfacelist = &surface;
12756
12757         // fake enough texture and surface state to render this geometry
12758         surface.texture = texture;
12759         surface.num_triangles = numtriangles;
12760         surface.num_firsttriangle = firsttriangle;
12761         surface.num_vertices = numvertices;
12762         surface.num_firstvertex = firstvertex;
12763
12764         // now render it
12765         rsurface.texture = R_GetCurrentTexture(surface.texture);
12766         rsurface.lightmaptexture = NULL;
12767         rsurface.deluxemaptexture = NULL;
12768         rsurface.uselightmaptexture = false;
12769         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12770 }