]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Disable r_water_hideplayer while in chase camera view
[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[1];
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, 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, 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 += strlen(vertstrings_list[i]);
1784         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1785         for (i = 0;i < vertstrings_count;t += 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 += strlen(geomstrings_list[i]);
1791         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1792         for (i = 0;i < geomstrings_count;t += 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 += strlen(fragstrings_list[i]);
1798         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1799         for (i = 0;i < fragstrings_count;t += 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 = 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 = 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
3404         if (ddsbase)
3405         {
3406                 skinframe->base = ddsbase;
3407                 skinframe->hasalpha = ddshasalpha;
3408                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3409                 if (r_loadfog && skinframe->hasalpha)
3410                         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);
3411                 //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]);
3412         }
3413         else
3414         {
3415                 basepixels_width = image_width;
3416                 basepixels_height = image_height;
3417                 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);
3418                 if (textureflags & TEXF_ALPHA)
3419                 {
3420                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3421                         {
3422                                 if (basepixels[j] < 255)
3423                                 {
3424                                         skinframe->hasalpha = true;
3425                                         break;
3426                                 }
3427                         }
3428                         if (r_loadfog && skinframe->hasalpha)
3429                         {
3430                                 // has transparent pixels
3431                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3432                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3433                                 {
3434                                         pixels[j+0] = 255;
3435                                         pixels[j+1] = 255;
3436                                         pixels[j+2] = 255;
3437                                         pixels[j+3] = basepixels[j+3];
3438                                 }
3439                                 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);
3440                                 Mem_Free(pixels);
3441                         }
3442                 }
3443                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3444 #ifndef USE_GLES2
3445                 //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]);
3446                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3447                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3448                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3449                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3450 #endif
3451         }
3452
3453         if (r_loaddds)
3454         {
3455                 mymiplevel = savemiplevel;
3456                 if (r_loadnormalmap)
3457                         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);
3458                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3459                 if (r_loadgloss)
3460                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3461                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3462                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3463                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3464         }
3465
3466         // _norm is the name used by tenebrae and has been adopted as standard
3467         if (r_loadnormalmap && skinframe->nmap == NULL)
3468         {
3469                 mymiplevel = savemiplevel;
3470                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3471                 {
3472                         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);
3473                         Mem_Free(pixels);
3474                         pixels = NULL;
3475                 }
3476                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3477                 {
3478                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3479                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3480                         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);
3481                         Mem_Free(pixels);
3482                         Mem_Free(bumppixels);
3483                 }
3484                 else if (r_shadow_bumpscale_basetexture.value > 0)
3485                 {
3486                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3487                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3488                         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);
3489                         Mem_Free(pixels);
3490                 }
3491 #ifndef USE_GLES2
3492                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3493                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3494 #endif
3495         }
3496
3497         // _luma is supported only for tenebrae compatibility
3498         // _glow is the preferred name
3499         mymiplevel = savemiplevel;
3500         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))))
3501         {
3502                 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);
3503 #ifndef USE_GLES2
3504                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3505                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3506 #endif
3507                 Mem_Free(pixels);pixels = NULL;
3508         }
3509
3510         mymiplevel = savemiplevel;
3511         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3512         {
3513                 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);
3514 #ifndef USE_GLES2
3515                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3516                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3517 #endif
3518                 Mem_Free(pixels);
3519                 pixels = NULL;
3520         }
3521
3522         mymiplevel = savemiplevel;
3523         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3524         {
3525                 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);
3526 #ifndef USE_GLES2
3527                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3528                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3529 #endif
3530                 Mem_Free(pixels);
3531                 pixels = NULL;
3532         }
3533
3534         mymiplevel = savemiplevel;
3535         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3536         {
3537                 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);
3538 #ifndef USE_GLES2
3539                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3540                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3541 #endif
3542                 Mem_Free(pixels);
3543                 pixels = NULL;
3544         }
3545
3546         mymiplevel = savemiplevel;
3547         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3548         {
3549                 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);
3550 #ifndef USE_GLES2
3551                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3552                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3553 #endif
3554                 Mem_Free(pixels);
3555                 pixels = NULL;
3556         }
3557
3558         if (basepixels)
3559                 Mem_Free(basepixels);
3560
3561         return skinframe;
3562 }
3563
3564 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3565 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3566 {
3567         int i;
3568         unsigned char *temp1, *temp2;
3569         skinframe_t *skinframe;
3570         char vabuf[1024];
3571
3572         if (cls.state == ca_dedicated)
3573                 return NULL;
3574
3575         // if already loaded just return it, otherwise make a new skinframe
3576         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3577         if (skinframe->base)
3578                 return skinframe;
3579         textureflags &= ~TEXF_FORCE_RELOAD;
3580
3581         skinframe->stain = NULL;
3582         skinframe->merged = NULL;
3583         skinframe->base = NULL;
3584         skinframe->pants = NULL;
3585         skinframe->shirt = NULL;
3586         skinframe->nmap = NULL;
3587         skinframe->gloss = NULL;
3588         skinframe->glow = NULL;
3589         skinframe->fog = NULL;
3590         skinframe->reflect = NULL;
3591         skinframe->hasalpha = false;
3592
3593         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3594         if (!skindata)
3595                 return NULL;
3596
3597         if (developer_loading.integer)
3598                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3599
3600         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3601         {
3602                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3603                 temp2 = temp1 + width * height * 4;
3604                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3605                 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);
3606                 Mem_Free(temp1);
3607         }
3608         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3609         if (textureflags & TEXF_ALPHA)
3610         {
3611                 for (i = 3;i < width * height * 4;i += 4)
3612                 {
3613                         if (skindata[i] < 255)
3614                         {
3615                                 skinframe->hasalpha = true;
3616                                 break;
3617                         }
3618                 }
3619                 if (r_loadfog && skinframe->hasalpha)
3620                 {
3621                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3622                         memcpy(fogpixels, skindata, width * height * 4);
3623                         for (i = 0;i < width * height * 4;i += 4)
3624                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3625                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3626                         Mem_Free(fogpixels);
3627                 }
3628         }
3629
3630         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3631         //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]);
3632
3633         return skinframe;
3634 }
3635
3636 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3637 {
3638         int i;
3639         int featuresmask;
3640         skinframe_t *skinframe;
3641
3642         if (cls.state == ca_dedicated)
3643                 return NULL;
3644
3645         // if already loaded just return it, otherwise make a new skinframe
3646         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3647         if (skinframe->base)
3648                 return skinframe;
3649         //textureflags &= ~TEXF_FORCE_RELOAD;
3650
3651         skinframe->stain = NULL;
3652         skinframe->merged = NULL;
3653         skinframe->base = NULL;
3654         skinframe->pants = NULL;
3655         skinframe->shirt = NULL;
3656         skinframe->nmap = NULL;
3657         skinframe->gloss = NULL;
3658         skinframe->glow = NULL;
3659         skinframe->fog = NULL;
3660         skinframe->reflect = NULL;
3661         skinframe->hasalpha = false;
3662
3663         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3664         if (!skindata)
3665                 return NULL;
3666
3667         if (developer_loading.integer)
3668                 Con_Printf("loading quake skin \"%s\"\n", name);
3669
3670         // 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)
3671         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3672         memcpy(skinframe->qpixels, skindata, width*height);
3673         skinframe->qwidth = width;
3674         skinframe->qheight = height;
3675
3676         featuresmask = 0;
3677         for (i = 0;i < width * height;i++)
3678                 featuresmask |= palette_featureflags[skindata[i]];
3679
3680         skinframe->hasalpha = false;
3681         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3682         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3683         skinframe->qgeneratemerged = true;
3684         skinframe->qgeneratebase = skinframe->qhascolormapping;
3685         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3686
3687         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3688         //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]);
3689
3690         return skinframe;
3691 }
3692
3693 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3694 {
3695         int width;
3696         int height;
3697         unsigned char *skindata;
3698         char vabuf[1024];
3699
3700         if (!skinframe->qpixels)
3701                 return;
3702
3703         if (!skinframe->qhascolormapping)
3704                 colormapped = false;
3705
3706         if (colormapped)
3707         {
3708                 if (!skinframe->qgeneratebase)
3709                         return;
3710         }
3711         else
3712         {
3713                 if (!skinframe->qgeneratemerged)
3714                         return;
3715         }
3716
3717         width = skinframe->qwidth;
3718         height = skinframe->qheight;
3719         skindata = skinframe->qpixels;
3720
3721         if (skinframe->qgeneratenmap)
3722         {
3723                 unsigned char *temp1, *temp2;
3724                 skinframe->qgeneratenmap = false;
3725                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3726                 temp2 = temp1 + width * height * 4;
3727                 // use either a custom palette or the quake palette
3728                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3729                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3730                 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);
3731                 Mem_Free(temp1);
3732         }
3733
3734         if (skinframe->qgenerateglow)
3735         {
3736                 skinframe->qgenerateglow = false;
3737                 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
3738         }
3739
3740         if (colormapped)
3741         {
3742                 skinframe->qgeneratebase = false;
3743                 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);
3744                 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);
3745                 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);
3746         }
3747         else
3748         {
3749                 skinframe->qgeneratemerged = false;
3750                 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);
3751         }
3752
3753         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3754         {
3755                 Mem_Free(skinframe->qpixels);
3756                 skinframe->qpixels = NULL;
3757         }
3758 }
3759
3760 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)
3761 {
3762         int i;
3763         skinframe_t *skinframe;
3764         char vabuf[1024];
3765
3766         if (cls.state == ca_dedicated)
3767                 return NULL;
3768
3769         // if already loaded just return it, otherwise make a new skinframe
3770         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3771         if (skinframe->base)
3772                 return skinframe;
3773         textureflags &= ~TEXF_FORCE_RELOAD;
3774
3775         skinframe->stain = NULL;
3776         skinframe->merged = NULL;
3777         skinframe->base = NULL;
3778         skinframe->pants = NULL;
3779         skinframe->shirt = NULL;
3780         skinframe->nmap = NULL;
3781         skinframe->gloss = NULL;
3782         skinframe->glow = NULL;
3783         skinframe->fog = NULL;
3784         skinframe->reflect = NULL;
3785         skinframe->hasalpha = false;
3786
3787         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3788         if (!skindata)
3789                 return NULL;
3790
3791         if (developer_loading.integer)
3792                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3793
3794         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3795         if (textureflags & TEXF_ALPHA)
3796         {
3797                 for (i = 0;i < width * height;i++)
3798                 {
3799                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3800                         {
3801                                 skinframe->hasalpha = true;
3802                                 break;
3803                         }
3804                 }
3805                 if (r_loadfog && skinframe->hasalpha)
3806                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3807         }
3808
3809         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3810         //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]);
3811
3812         return skinframe;
3813 }
3814
3815 skinframe_t *R_SkinFrame_LoadMissing(void)
3816 {
3817         skinframe_t *skinframe;
3818
3819         if (cls.state == ca_dedicated)
3820                 return NULL;
3821
3822         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3823         skinframe->stain = NULL;
3824         skinframe->merged = NULL;
3825         skinframe->base = NULL;
3826         skinframe->pants = NULL;
3827         skinframe->shirt = NULL;
3828         skinframe->nmap = NULL;
3829         skinframe->gloss = NULL;
3830         skinframe->glow = NULL;
3831         skinframe->fog = NULL;
3832         skinframe->reflect = NULL;
3833         skinframe->hasalpha = false;
3834
3835         skinframe->avgcolor[0] = rand() / RAND_MAX;
3836         skinframe->avgcolor[1] = rand() / RAND_MAX;
3837         skinframe->avgcolor[2] = rand() / RAND_MAX;
3838         skinframe->avgcolor[3] = 1;
3839
3840         return skinframe;
3841 }
3842
3843 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3844 typedef struct suffixinfo_s
3845 {
3846         const char *suffix;
3847         qboolean flipx, flipy, flipdiagonal;
3848 }
3849 suffixinfo_t;
3850 static suffixinfo_t suffix[3][6] =
3851 {
3852         {
3853                 {"px",   false, false, false},
3854                 {"nx",   false, false, false},
3855                 {"py",   false, false, false},
3856                 {"ny",   false, false, false},
3857                 {"pz",   false, false, false},
3858                 {"nz",   false, false, false}
3859         },
3860         {
3861                 {"posx", false, false, false},
3862                 {"negx", false, false, false},
3863                 {"posy", false, false, false},
3864                 {"negy", false, false, false},
3865                 {"posz", false, false, false},
3866                 {"negz", false, false, false}
3867         },
3868         {
3869                 {"rt",    true, false,  true},
3870                 {"lf",   false,  true,  true},
3871                 {"ft",    true,  true, false},
3872                 {"bk",   false, false, false},
3873                 {"up",    true, false,  true},
3874                 {"dn",    true, false,  true}
3875         }
3876 };
3877
3878 static int componentorder[4] = {0, 1, 2, 3};
3879
3880 static rtexture_t *R_LoadCubemap(const char *basename)
3881 {
3882         int i, j, cubemapsize;
3883         unsigned char *cubemappixels, *image_buffer;
3884         rtexture_t *cubemaptexture;
3885         char name[256];
3886         // must start 0 so the first loadimagepixels has no requested width/height
3887         cubemapsize = 0;
3888         cubemappixels = NULL;
3889         cubemaptexture = NULL;
3890         // keep trying different suffix groups (posx, px, rt) until one loads
3891         for (j = 0;j < 3 && !cubemappixels;j++)
3892         {
3893                 // load the 6 images in the suffix group
3894                 for (i = 0;i < 6;i++)
3895                 {
3896                         // generate an image name based on the base and and suffix
3897                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3898                         // load it
3899                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3900                         {
3901                                 // an image loaded, make sure width and height are equal
3902                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3903                                 {
3904                                         // if this is the first image to load successfully, allocate the cubemap memory
3905                                         if (!cubemappixels && image_width >= 1)
3906                                         {
3907                                                 cubemapsize = image_width;
3908                                                 // note this clears to black, so unavailable sides are black
3909                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3910                                         }
3911                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3912                                         if (cubemappixels)
3913                                                 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);
3914                                 }
3915                                 else
3916                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3917                                 // free the image
3918                                 Mem_Free(image_buffer);
3919                         }
3920                 }
3921         }
3922         // if a cubemap loaded, upload it
3923         if (cubemappixels)
3924         {
3925                 if (developer_loading.integer)
3926                         Con_Printf("loading cubemap \"%s\"\n", basename);
3927
3928                 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);
3929                 Mem_Free(cubemappixels);
3930         }
3931         else
3932         {
3933                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3934                 if (developer_loading.integer)
3935                 {
3936                         Con_Printf("(tried tried images ");
3937                         for (j = 0;j < 3;j++)
3938                                 for (i = 0;i < 6;i++)
3939                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3940                         Con_Print(" and was unable to find any of them).\n");
3941                 }
3942         }
3943         return cubemaptexture;
3944 }
3945
3946 rtexture_t *R_GetCubemap(const char *basename)
3947 {
3948         int i;
3949         for (i = 0;i < r_texture_numcubemaps;i++)
3950                 if (r_texture_cubemaps[i] != NULL)
3951                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3952                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3953         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3954                 return r_texture_whitecube;
3955         r_texture_numcubemaps++;
3956         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3957         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3958         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3959         return r_texture_cubemaps[i]->texture;
3960 }
3961
3962 static void R_Main_FreeViewCache(void)
3963 {
3964         if (r_refdef.viewcache.entityvisible)
3965                 Mem_Free(r_refdef.viewcache.entityvisible);
3966         if (r_refdef.viewcache.world_pvsbits)
3967                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3968         if (r_refdef.viewcache.world_leafvisible)
3969                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3970         if (r_refdef.viewcache.world_surfacevisible)
3971                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3972         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3973 }
3974
3975 static void R_Main_ResizeViewCache(void)
3976 {
3977         int numentities = r_refdef.scene.numentities;
3978         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3979         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3980         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3981         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3982         if (r_refdef.viewcache.maxentities < numentities)
3983         {
3984                 r_refdef.viewcache.maxentities = numentities;
3985                 if (r_refdef.viewcache.entityvisible)
3986                         Mem_Free(r_refdef.viewcache.entityvisible);
3987                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3988         }
3989         if (r_refdef.viewcache.world_numclusters != numclusters)
3990         {
3991                 r_refdef.viewcache.world_numclusters = numclusters;
3992                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3993                 if (r_refdef.viewcache.world_pvsbits)
3994                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3995                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3996         }
3997         if (r_refdef.viewcache.world_numleafs != numleafs)
3998         {
3999                 r_refdef.viewcache.world_numleafs = numleafs;
4000                 if (r_refdef.viewcache.world_leafvisible)
4001                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4002                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4003         }
4004         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4005         {
4006                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4007                 if (r_refdef.viewcache.world_surfacevisible)
4008                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4009                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4010         }
4011 }
4012
4013 extern rtexture_t *loadingscreentexture;
4014 static void gl_main_start(void)
4015 {
4016         loadingscreentexture = NULL;
4017         r_texture_blanknormalmap = NULL;
4018         r_texture_white = NULL;
4019         r_texture_grey128 = NULL;
4020         r_texture_black = NULL;
4021         r_texture_whitecube = NULL;
4022         r_texture_normalizationcube = NULL;
4023         r_texture_fogattenuation = NULL;
4024         r_texture_fogheighttexture = NULL;
4025         r_texture_gammaramps = NULL;
4026         r_texture_numcubemaps = 0;
4027         r_uniformbufferalignment = 32;
4028
4029         r_loaddds = r_texture_dds_load.integer != 0;
4030         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4031
4032         switch(vid.renderpath)
4033         {
4034         case RENDERPATH_GL20:
4035         case RENDERPATH_D3D9:
4036         case RENDERPATH_D3D10:
4037         case RENDERPATH_D3D11:
4038         case RENDERPATH_SOFT:
4039         case RENDERPATH_GLES2:
4040                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4041                 Cvar_SetValueQuick(&gl_combine, 1);
4042                 Cvar_SetValueQuick(&r_glsl, 1);
4043                 r_loadnormalmap = true;
4044                 r_loadgloss = true;
4045                 r_loadfog = false;
4046 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4047                 if (vid.support.arb_uniform_buffer_object)
4048                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4049 #endif
4050                         break;
4051         case RENDERPATH_GL13:
4052         case RENDERPATH_GLES1:
4053                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4054                 Cvar_SetValueQuick(&gl_combine, 1);
4055                 Cvar_SetValueQuick(&r_glsl, 0);
4056                 r_loadnormalmap = false;
4057                 r_loadgloss = false;
4058                 r_loadfog = true;
4059                 break;
4060         case RENDERPATH_GL11:
4061                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4062                 Cvar_SetValueQuick(&gl_combine, 0);
4063                 Cvar_SetValueQuick(&r_glsl, 0);
4064                 r_loadnormalmap = false;
4065                 r_loadgloss = false;
4066                 r_loadfog = true;
4067                 break;
4068         }
4069
4070         R_AnimCache_Free();
4071         R_FrameData_Reset();
4072         R_BufferData_Reset();
4073
4074         r_numqueries = 0;
4075         r_maxqueries = 0;
4076         memset(r_queries, 0, sizeof(r_queries));
4077
4078         r_qwskincache = NULL;
4079         r_qwskincache_size = 0;
4080
4081         // due to caching of texture_t references, the collision cache must be reset
4082         Collision_Cache_Reset(true);
4083
4084         // set up r_skinframe loading system for textures
4085         memset(&r_skinframe, 0, sizeof(r_skinframe));
4086         r_skinframe.loadsequence = 1;
4087         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4088
4089         r_main_texturepool = R_AllocTexturePool();
4090         R_BuildBlankTextures();
4091         R_BuildNoTexture();
4092         if (vid.support.arb_texture_cube_map)
4093         {
4094                 R_BuildWhiteCube();
4095                 R_BuildNormalizationCube();
4096         }
4097         r_texture_fogattenuation = NULL;
4098         r_texture_fogheighttexture = NULL;
4099         r_texture_gammaramps = NULL;
4100         //r_texture_fogintensity = NULL;
4101         memset(&r_fb, 0, sizeof(r_fb));
4102         r_glsl_permutation = NULL;
4103         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4104         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4105         glslshaderstring = NULL;
4106 #ifdef SUPPORTD3D
4107         r_hlsl_permutation = NULL;
4108         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4109         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4110 #endif
4111         hlslshaderstring = NULL;
4112         memset(&r_svbsp, 0, sizeof (r_svbsp));
4113
4114         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4115         r_texture_numcubemaps = 0;
4116
4117         r_refdef.fogmasktable_density = 0;
4118
4119 #ifdef __ANDROID__
4120         // For Steelstorm Android
4121         // FIXME CACHE the program and reload
4122         // FIXME see possible combinations for SS:BR android
4123         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4124         R_SetupShader_SetPermutationGLSL(0, 12);
4125         R_SetupShader_SetPermutationGLSL(0, 13);
4126         R_SetupShader_SetPermutationGLSL(0, 8388621);
4127         R_SetupShader_SetPermutationGLSL(3, 0);
4128         R_SetupShader_SetPermutationGLSL(3, 2048);
4129         R_SetupShader_SetPermutationGLSL(5, 0);
4130         R_SetupShader_SetPermutationGLSL(5, 2);
4131         R_SetupShader_SetPermutationGLSL(5, 2048);
4132         R_SetupShader_SetPermutationGLSL(5, 8388608);
4133         R_SetupShader_SetPermutationGLSL(11, 1);
4134         R_SetupShader_SetPermutationGLSL(11, 2049);
4135         R_SetupShader_SetPermutationGLSL(11, 8193);
4136         R_SetupShader_SetPermutationGLSL(11, 10241);
4137         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4138 #endif
4139 }
4140
4141 static void gl_main_shutdown(void)
4142 {
4143         R_AnimCache_Free();
4144         R_FrameData_Reset();
4145         R_BufferData_Reset();
4146
4147         R_Main_FreeViewCache();
4148
4149         switch(vid.renderpath)
4150         {
4151         case RENDERPATH_GL11:
4152         case RENDERPATH_GL13:
4153         case RENDERPATH_GL20:
4154         case RENDERPATH_GLES1:
4155         case RENDERPATH_GLES2:
4156 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4157                 if (r_maxqueries)
4158                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4159 #endif
4160                 break;
4161         case RENDERPATH_D3D9:
4162                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4163                 break;
4164         case RENDERPATH_D3D10:
4165                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4166                 break;
4167         case RENDERPATH_D3D11:
4168                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4169                 break;
4170         case RENDERPATH_SOFT:
4171                 break;
4172         }
4173
4174         r_numqueries = 0;
4175         r_maxqueries = 0;
4176         memset(r_queries, 0, sizeof(r_queries));
4177
4178         r_qwskincache = NULL;
4179         r_qwskincache_size = 0;
4180
4181         // clear out the r_skinframe state
4182         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4183         memset(&r_skinframe, 0, sizeof(r_skinframe));
4184
4185         if (r_svbsp.nodes)
4186                 Mem_Free(r_svbsp.nodes);
4187         memset(&r_svbsp, 0, sizeof (r_svbsp));
4188         R_FreeTexturePool(&r_main_texturepool);
4189         loadingscreentexture = NULL;
4190         r_texture_blanknormalmap = NULL;
4191         r_texture_white = NULL;
4192         r_texture_grey128 = NULL;
4193         r_texture_black = NULL;
4194         r_texture_whitecube = NULL;
4195         r_texture_normalizationcube = NULL;
4196         r_texture_fogattenuation = NULL;
4197         r_texture_fogheighttexture = NULL;
4198         r_texture_gammaramps = NULL;
4199         r_texture_numcubemaps = 0;
4200         //r_texture_fogintensity = NULL;
4201         memset(&r_fb, 0, sizeof(r_fb));
4202         R_GLSL_Restart_f();
4203
4204         r_glsl_permutation = NULL;
4205         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4206         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4207         glslshaderstring = NULL;
4208 #ifdef SUPPORTD3D
4209         r_hlsl_permutation = NULL;
4210         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4211         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4212 #endif
4213         hlslshaderstring = NULL;
4214 }
4215
4216 static void gl_main_newmap(void)
4217 {
4218         // FIXME: move this code to client
4219         char *entities, entname[MAX_QPATH];
4220         if (r_qwskincache)
4221                 Mem_Free(r_qwskincache);
4222         r_qwskincache = NULL;
4223         r_qwskincache_size = 0;
4224         if (cl.worldmodel)
4225         {
4226                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4227                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4228                 {
4229                         CL_ParseEntityLump(entities);
4230                         Mem_Free(entities);
4231                         return;
4232                 }
4233                 if (cl.worldmodel->brush.entities)
4234                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4235         }
4236         R_Main_FreeViewCache();
4237
4238         R_FrameData_Reset();
4239         R_BufferData_Reset();
4240 }
4241
4242 void GL_Main_Init(void)
4243 {
4244         int i;
4245         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4246
4247         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4248         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4249         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4250         if (gamemode == GAME_NEHAHRA)
4251         {
4252                 Cvar_RegisterVariable (&gl_fogenable);
4253                 Cvar_RegisterVariable (&gl_fogdensity);
4254                 Cvar_RegisterVariable (&gl_fogred);
4255                 Cvar_RegisterVariable (&gl_foggreen);
4256                 Cvar_RegisterVariable (&gl_fogblue);
4257                 Cvar_RegisterVariable (&gl_fogstart);
4258                 Cvar_RegisterVariable (&gl_fogend);
4259                 Cvar_RegisterVariable (&gl_skyclip);
4260         }
4261         Cvar_RegisterVariable(&r_motionblur);
4262         Cvar_RegisterVariable(&r_damageblur);
4263         Cvar_RegisterVariable(&r_motionblur_averaging);
4264         Cvar_RegisterVariable(&r_motionblur_randomize);
4265         Cvar_RegisterVariable(&r_motionblur_minblur);
4266         Cvar_RegisterVariable(&r_motionblur_maxblur);
4267         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4268         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4269         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4270         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4271         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4272         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4273         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4274         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4275         Cvar_RegisterVariable(&r_equalize_entities_by);
4276         Cvar_RegisterVariable(&r_equalize_entities_to);
4277         Cvar_RegisterVariable(&r_depthfirst);
4278         Cvar_RegisterVariable(&r_useinfinitefarclip);
4279         Cvar_RegisterVariable(&r_farclip_base);
4280         Cvar_RegisterVariable(&r_farclip_world);
4281         Cvar_RegisterVariable(&r_nearclip);
4282         Cvar_RegisterVariable(&r_deformvertexes);
4283         Cvar_RegisterVariable(&r_transparent);
4284         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4285         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4286         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4287         Cvar_RegisterVariable(&r_showoverdraw);
4288         Cvar_RegisterVariable(&r_showbboxes);
4289         Cvar_RegisterVariable(&r_showsurfaces);
4290         Cvar_RegisterVariable(&r_showtris);
4291         Cvar_RegisterVariable(&r_shownormals);
4292         Cvar_RegisterVariable(&r_showlighting);
4293         Cvar_RegisterVariable(&r_showshadowvolumes);
4294         Cvar_RegisterVariable(&r_showcollisionbrushes);
4295         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4296         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4297         Cvar_RegisterVariable(&r_showdisabledepthtest);
4298         Cvar_RegisterVariable(&r_drawportals);
4299         Cvar_RegisterVariable(&r_drawentities);
4300         Cvar_RegisterVariable(&r_draw2d);
4301         Cvar_RegisterVariable(&r_drawworld);
4302         Cvar_RegisterVariable(&r_cullentities_trace);
4303         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4304         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4305         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4306         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4307         Cvar_RegisterVariable(&r_sortentities);
4308         Cvar_RegisterVariable(&r_drawviewmodel);
4309         Cvar_RegisterVariable(&r_drawexteriormodel);
4310         Cvar_RegisterVariable(&r_speeds);
4311         Cvar_RegisterVariable(&r_fullbrights);
4312         Cvar_RegisterVariable(&r_wateralpha);
4313         Cvar_RegisterVariable(&r_dynamic);
4314         Cvar_RegisterVariable(&r_fakelight);
4315         Cvar_RegisterVariable(&r_fakelight_intensity);
4316         Cvar_RegisterVariable(&r_fullbright);
4317         Cvar_RegisterVariable(&r_shadows);
4318         Cvar_RegisterVariable(&r_shadows_darken);
4319         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4320         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4321         Cvar_RegisterVariable(&r_shadows_throwdistance);
4322         Cvar_RegisterVariable(&r_shadows_throwdirection);
4323         Cvar_RegisterVariable(&r_shadows_focus);
4324         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4325         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4326         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4327         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4328         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4329         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4330         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4331         Cvar_RegisterVariable(&r_fog_exp2);
4332         Cvar_RegisterVariable(&r_fog_clear);
4333         Cvar_RegisterVariable(&r_drawfog);
4334         Cvar_RegisterVariable(&r_transparentdepthmasking);
4335         Cvar_RegisterVariable(&r_transparent_sortmindist);
4336         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4337         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4338         Cvar_RegisterVariable(&r_texture_dds_load);
4339         Cvar_RegisterVariable(&r_texture_dds_save);
4340         Cvar_RegisterVariable(&r_textureunits);
4341         Cvar_RegisterVariable(&gl_combine);
4342         Cvar_RegisterVariable(&r_usedepthtextures);
4343         Cvar_RegisterVariable(&r_viewfbo);
4344         Cvar_RegisterVariable(&r_viewscale);
4345         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4346         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4347         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4348         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4349         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4350         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4351         Cvar_RegisterVariable(&r_glsl);
4352         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4353         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4354         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4355         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4356         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4357         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4358         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4359         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4360         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4361         Cvar_RegisterVariable(&r_glsl_postprocess);
4362         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4363         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4364         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4365         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4366         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4367         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4368         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4369         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4370         Cvar_RegisterVariable(&r_celshading);
4371         Cvar_RegisterVariable(&r_celoutlines);
4372
4373         Cvar_RegisterVariable(&r_water);
4374         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4375         Cvar_RegisterVariable(&r_water_clippingplanebias);
4376         Cvar_RegisterVariable(&r_water_refractdistort);
4377         Cvar_RegisterVariable(&r_water_reflectdistort);
4378         Cvar_RegisterVariable(&r_water_scissormode);
4379         Cvar_RegisterVariable(&r_water_lowquality);
4380         Cvar_RegisterVariable(&r_water_hideplayer);
4381         Cvar_RegisterVariable(&r_water_fbo);
4382
4383         Cvar_RegisterVariable(&r_lerpsprites);
4384         Cvar_RegisterVariable(&r_lerpmodels);
4385         Cvar_RegisterVariable(&r_lerplightstyles);
4386         Cvar_RegisterVariable(&r_waterscroll);
4387         Cvar_RegisterVariable(&r_bloom);
4388         Cvar_RegisterVariable(&r_bloom_colorscale);
4389         Cvar_RegisterVariable(&r_bloom_brighten);
4390         Cvar_RegisterVariable(&r_bloom_blur);
4391         Cvar_RegisterVariable(&r_bloom_resolution);
4392         Cvar_RegisterVariable(&r_bloom_colorexponent);
4393         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4394         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4395         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4396         Cvar_RegisterVariable(&r_hdr_glowintensity);
4397         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4398         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4399         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4400         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4401         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4402         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4403         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4404         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4405         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4406         Cvar_RegisterVariable(&developer_texturelogging);
4407         Cvar_RegisterVariable(&gl_lightmaps);
4408         Cvar_RegisterVariable(&r_test);
4409         Cvar_RegisterVariable(&r_batch_multidraw);
4410         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4411         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4412         Cvar_RegisterVariable(&r_glsl_skeletal);
4413         Cvar_RegisterVariable(&r_glsl_saturation);
4414         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4415         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4416         Cvar_RegisterVariable(&r_framedatasize);
4417         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4418                 Cvar_RegisterVariable(&r_buffermegs[i]);
4419         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4420         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4421                 Cvar_SetValue("r_fullbrights", 0);
4422 #ifdef DP_MOBILETOUCH
4423         // GLES devices have terrible depth precision in general, so...
4424         Cvar_SetValueQuick(&r_nearclip, 4);
4425         Cvar_SetValueQuick(&r_farclip_base, 4096);
4426         Cvar_SetValueQuick(&r_farclip_world, 0);
4427         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4428 #endif
4429         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4430 }
4431
4432 void Render_Init(void)
4433 {
4434         gl_backend_init();
4435         R_Textures_Init();
4436         GL_Main_Init();
4437         Font_Init();
4438         GL_Draw_Init();
4439         R_Shadow_Init();
4440         R_Sky_Init();
4441         GL_Surf_Init();
4442         Sbar_Init();
4443         R_Particles_Init();
4444         R_Explosion_Init();
4445         R_LightningBeams_Init();
4446         Mod_RenderInit();
4447 }
4448
4449 /*
4450 ===============
4451 GL_Init
4452 ===============
4453 */
4454 #ifndef USE_GLES2
4455 extern char *ENGINE_EXTENSIONS;
4456 void GL_Init (void)
4457 {
4458         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4459         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4460         gl_version = (const char *)qglGetString(GL_VERSION);
4461         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4462
4463         if (!gl_extensions)
4464                 gl_extensions = "";
4465         if (!gl_platformextensions)
4466                 gl_platformextensions = "";
4467
4468         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4469         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4470         Con_Printf("GL_VERSION: %s\n", gl_version);
4471         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4472         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4473
4474         VID_CheckExtensions();
4475
4476         // LordHavoc: report supported extensions
4477 #ifdef CONFIG_MENU
4478         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4479 #else
4480         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4481 #endif
4482
4483         // clear to black (loading plaque will be seen over this)
4484         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4485 }
4486 #endif
4487
4488 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4489 {
4490         int i;
4491         mplane_t *p;
4492         if (r_trippy.integer)
4493                 return false;
4494         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4495         {
4496                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4497                 if (i == 4)
4498                         continue;
4499                 p = r_refdef.view.frustum + i;
4500                 switch(p->signbits)
4501                 {
4502                 default:
4503                 case 0:
4504                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4505                                 return true;
4506                         break;
4507                 case 1:
4508                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4509                                 return true;
4510                         break;
4511                 case 2:
4512                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4513                                 return true;
4514                         break;
4515                 case 3:
4516                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4517                                 return true;
4518                         break;
4519                 case 4:
4520                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4521                                 return true;
4522                         break;
4523                 case 5:
4524                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4525                                 return true;
4526                         break;
4527                 case 6:
4528                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4529                                 return true;
4530                         break;
4531                 case 7:
4532                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4533                                 return true;
4534                         break;
4535                 }
4536         }
4537         return false;
4538 }
4539
4540 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4541 {
4542         int i;
4543         const mplane_t *p;
4544         if (r_trippy.integer)
4545                 return false;
4546         for (i = 0;i < numplanes;i++)
4547         {
4548                 p = planes + i;
4549                 switch(p->signbits)
4550                 {
4551                 default:
4552                 case 0:
4553                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4554                                 return true;
4555                         break;
4556                 case 1:
4557                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4558                                 return true;
4559                         break;
4560                 case 2:
4561                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4562                                 return true;
4563                         break;
4564                 case 3:
4565                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4566                                 return true;
4567                         break;
4568                 case 4:
4569                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4570                                 return true;
4571                         break;
4572                 case 5:
4573                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4574                                 return true;
4575                         break;
4576                 case 6:
4577                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4578                                 return true;
4579                         break;
4580                 case 7:
4581                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4582                                 return true;
4583                         break;
4584                 }
4585         }
4586         return false;
4587 }
4588
4589 //==================================================================================
4590
4591 // LordHavoc: this stores temporary data used within the same frame
4592
4593 typedef struct r_framedata_mem_s
4594 {
4595         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4596         size_t size; // how much usable space
4597         size_t current; // how much space in use
4598         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4599         size_t wantedsize; // how much space was allocated
4600         unsigned char *data; // start of real data (16byte aligned)
4601 }
4602 r_framedata_mem_t;
4603
4604 static r_framedata_mem_t *r_framedata_mem;
4605
4606 void R_FrameData_Reset(void)
4607 {
4608         while (r_framedata_mem)
4609         {
4610                 r_framedata_mem_t *next = r_framedata_mem->purge;
4611                 Mem_Free(r_framedata_mem);
4612                 r_framedata_mem = next;
4613         }
4614 }
4615
4616 static void R_FrameData_Resize(qboolean mustgrow)
4617 {
4618         size_t wantedsize;
4619         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4620         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4621         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4622         {
4623                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4624                 newmem->wantedsize = wantedsize;
4625                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4626                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4627                 newmem->current = 0;
4628                 newmem->mark = 0;
4629                 newmem->purge = r_framedata_mem;
4630                 r_framedata_mem = newmem;
4631         }
4632 }
4633
4634 void R_FrameData_NewFrame(void)
4635 {
4636         R_FrameData_Resize(false);
4637         if (!r_framedata_mem)
4638                 return;
4639         // if we ran out of space on the last frame, free the old memory now
4640         while (r_framedata_mem->purge)
4641         {
4642                 // repeatedly remove the second item in the list, leaving only head
4643                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4644                 Mem_Free(r_framedata_mem->purge);
4645                 r_framedata_mem->purge = next;
4646         }
4647         // reset the current mem pointer
4648         r_framedata_mem->current = 0;
4649         r_framedata_mem->mark = 0;
4650 }
4651
4652 void *R_FrameData_Alloc(size_t size)
4653 {
4654         void *data;
4655         float newvalue;
4656
4657         // align to 16 byte boundary - the data pointer is already aligned, so we
4658         // only need to ensure the size of every allocation is also aligned
4659         size = (size + 15) & ~15;
4660
4661         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4662         {
4663                 // emergency - we ran out of space, allocate more memory
4664                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4665                 // this might not be a growing it, but we'll allocate another buffer every time
4666                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4667                 R_FrameData_Resize(true);
4668         }
4669
4670         data = r_framedata_mem->data + r_framedata_mem->current;
4671         r_framedata_mem->current += size;
4672
4673         // count the usage for stats
4674         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4675         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4676
4677         return (void *)data;
4678 }
4679
4680 void *R_FrameData_Store(size_t size, void *data)
4681 {
4682         void *d = R_FrameData_Alloc(size);
4683         if (d && data)
4684                 memcpy(d, data, size);
4685         return d;
4686 }
4687
4688 void R_FrameData_SetMark(void)
4689 {
4690         if (!r_framedata_mem)
4691                 return;
4692         r_framedata_mem->mark = r_framedata_mem->current;
4693 }
4694
4695 void R_FrameData_ReturnToMark(void)
4696 {
4697         if (!r_framedata_mem)
4698                 return;
4699         r_framedata_mem->current = r_framedata_mem->mark;
4700 }
4701
4702 //==================================================================================
4703
4704 // avoid reusing the same buffer objects on consecutive frames
4705 #define R_BUFFERDATA_CYCLE 3
4706
4707 typedef struct r_bufferdata_buffer_s
4708 {
4709         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4710         size_t size; // how much usable space
4711         size_t current; // how much space in use
4712         r_meshbuffer_t *buffer; // the buffer itself
4713 }
4714 r_bufferdata_buffer_t;
4715
4716 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4717 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4718
4719 /// frees all dynamic buffers
4720 void R_BufferData_Reset(void)
4721 {
4722         int cycle, type;
4723         r_bufferdata_buffer_t **p, *mem;
4724         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4725         {
4726                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4727                 {
4728                         // free all buffers
4729                         p = &r_bufferdata_buffer[cycle][type];
4730                         while (*p)
4731                         {
4732                                 mem = *p;
4733                                 *p = (*p)->purge;
4734                                 if (mem->buffer)
4735                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4736                                 Mem_Free(mem);
4737                         }
4738                 }
4739         }
4740 }
4741
4742 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4743 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4744 {
4745         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4746         size_t size;
4747         float newvalue = r_buffermegs[type].value;
4748
4749         // increase the cvar if we have to (but only if we already have a mem)
4750         if (mustgrow && mem)
4751                 newvalue *= 2.0f;
4752         newvalue = bound(0.25f, newvalue, 256.0f);
4753         while (newvalue * 1024*1024 < minsize)
4754                 newvalue *= 2.0f;
4755
4756         // clamp the cvar to valid range
4757         newvalue = bound(0.25f, newvalue, 256.0f);
4758         if (r_buffermegs[type].value != newvalue)
4759                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4760
4761         // calculate size in bytes
4762         size = (size_t)(newvalue * 1024*1024);
4763         size = bound(131072, size, 256*1024*1024);
4764
4765         // allocate a new buffer if the size is different (purge old one later)
4766         // or if we were told we must grow the buffer
4767         if (!mem || mem->size != size || mustgrow)
4768         {
4769                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4770                 mem->size = size;
4771                 mem->current = 0;
4772                 if (type == R_BUFFERDATA_VERTEX)
4773                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4774                 else if (type == R_BUFFERDATA_INDEX16)
4775                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4776                 else if (type == R_BUFFERDATA_INDEX32)
4777                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4778                 else if (type == R_BUFFERDATA_UNIFORM)
4779                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4780                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4781                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4782         }
4783 }
4784
4785 void R_BufferData_NewFrame(void)
4786 {
4787         int type;
4788         r_bufferdata_buffer_t **p, *mem;
4789         // cycle to the next frame's buffers
4790         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4791         // if we ran out of space on the last time we used these buffers, free the old memory now
4792         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4793         {
4794                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4795                 {
4796                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4797                         // free all but the head buffer, this is how we recycle obsolete
4798                         // buffers after they are no longer in use
4799                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4800                         while (*p)
4801                         {
4802                                 mem = *p;
4803                                 *p = (*p)->purge;
4804                                 if (mem->buffer)
4805                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4806                                 Mem_Free(mem);
4807                         }
4808                         // reset the current offset
4809                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4810                 }
4811         }
4812 }
4813
4814 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4815 {
4816         r_bufferdata_buffer_t *mem;
4817         int offset = 0;
4818         int padsize;
4819
4820         *returnbufferoffset = 0;
4821
4822         // align size to a byte boundary appropriate for the buffer type, this
4823         // makes all allocations have aligned start offsets
4824         if (type == R_BUFFERDATA_UNIFORM)
4825                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4826         else
4827                 padsize = (datasize + 15) & ~15;
4828
4829         // if we ran out of space in this buffer we must allocate a new one
4830         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)
4831                 R_BufferData_Resize(type, true, padsize);
4832
4833         // if the resize did not give us enough memory, fail
4834         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)
4835                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4836
4837         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4838         offset = mem->current;
4839         mem->current += padsize;
4840
4841         // upload the data to the buffer at the chosen offset
4842         if (offset == 0)
4843                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4844         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4845
4846         // count the usage for stats
4847         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4848         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4849
4850         // return the buffer offset
4851         *returnbufferoffset = offset;
4852
4853         return mem->buffer;
4854 }
4855
4856 //==================================================================================
4857
4858 // LordHavoc: animcache originally written by Echon, rewritten since then
4859
4860 /**
4861  * Animation cache prevents re-generating mesh data for an animated model
4862  * multiple times in one frame for lighting, shadowing, reflections, etc.
4863  */
4864
4865 void R_AnimCache_Free(void)
4866 {
4867 }
4868
4869 void R_AnimCache_ClearCache(void)
4870 {
4871         int i;
4872         entity_render_t *ent;
4873
4874         for (i = 0;i < r_refdef.scene.numentities;i++)
4875         {
4876                 ent = r_refdef.scene.entities[i];
4877                 ent->animcache_vertex3f = NULL;
4878                 ent->animcache_vertex3f_vertexbuffer = NULL;
4879                 ent->animcache_vertex3f_bufferoffset = 0;
4880                 ent->animcache_normal3f = NULL;
4881                 ent->animcache_normal3f_vertexbuffer = NULL;
4882                 ent->animcache_normal3f_bufferoffset = 0;
4883                 ent->animcache_svector3f = NULL;
4884                 ent->animcache_svector3f_vertexbuffer = NULL;
4885                 ent->animcache_svector3f_bufferoffset = 0;
4886                 ent->animcache_tvector3f = NULL;
4887                 ent->animcache_tvector3f_vertexbuffer = NULL;
4888                 ent->animcache_tvector3f_bufferoffset = 0;
4889                 ent->animcache_vertexmesh = NULL;
4890                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4891                 ent->animcache_vertexmesh_bufferoffset = 0;
4892                 ent->animcache_skeletaltransform3x4 = NULL;
4893                 ent->animcache_skeletaltransform3x4buffer = NULL;
4894                 ent->animcache_skeletaltransform3x4offset = 0;
4895                 ent->animcache_skeletaltransform3x4size = 0;
4896         }
4897 }
4898
4899 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4900 {
4901         int i;
4902
4903         // check if we need the meshbuffers
4904         if (!vid.useinterleavedarrays)
4905                 return;
4906
4907         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4908                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4909         // TODO: upload vertexbuffer?
4910         if (ent->animcache_vertexmesh)
4911         {
4912                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4913                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4914                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4915                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4916                 for (i = 0;i < numvertices;i++)
4917                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4918                 if (ent->animcache_svector3f)
4919                         for (i = 0;i < numvertices;i++)
4920                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4921                 if (ent->animcache_tvector3f)
4922                         for (i = 0;i < numvertices;i++)
4923                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4924                 if (ent->animcache_normal3f)
4925                         for (i = 0;i < numvertices;i++)
4926                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4927         }
4928 }
4929
4930 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4931 {
4932         dp_model_t *model = ent->model;
4933         int numvertices;
4934
4935         // see if this ent is worth caching
4936         if (!model || !model->Draw || !model->AnimateVertices)
4937                 return false;
4938         // nothing to cache if it contains no animations and has no skeleton
4939         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4940                 return false;
4941         // see if it is already cached for gpuskeletal
4942         if (ent->animcache_skeletaltransform3x4)
4943                 return false;
4944         // see if it is already cached as a mesh
4945         if (ent->animcache_vertex3f)
4946         {
4947                 // check if we need to add normals or tangents
4948                 if (ent->animcache_normal3f)
4949                         wantnormals = false;
4950                 if (ent->animcache_svector3f)
4951                         wanttangents = false;
4952                 if (!wantnormals && !wanttangents)
4953                         return false;
4954         }
4955
4956         // check which kind of cache we need to generate
4957         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4958         {
4959                 // cache the skeleton so the vertex shader can use it
4960                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4961                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4962                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4963                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4964                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4965                 // note: this can fail if the buffer is at the grow limit
4966                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4967                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4968         }
4969         else if (ent->animcache_vertex3f)
4970         {
4971                 // mesh was already cached but we may need to add normals/tangents
4972                 // (this only happens with multiple views, reflections, cameras, etc)
4973                 if (wantnormals || wanttangents)
4974                 {
4975                         numvertices = model->surfmesh.num_vertices;
4976                         if (wantnormals)
4977                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4978                         if (wanttangents)
4979                         {
4980                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4981                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4982                         }
4983                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4984                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4985                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4986                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4987                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4988                 }
4989         }
4990         else
4991         {
4992                 // generate mesh cache
4993                 numvertices = model->surfmesh.num_vertices;
4994                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4995                 if (wantnormals)
4996                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4997                 if (wanttangents)
4998                 {
4999                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5000                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5001                 }
5002                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5003                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5004                 if (wantnormals || wanttangents)
5005                 {
5006                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5007                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5008                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5009                 }
5010                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5011                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5012                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5013         }
5014         return true;
5015 }
5016
5017 void R_AnimCache_CacheVisibleEntities(void)
5018 {
5019         int i;
5020         qboolean wantnormals = true;
5021         qboolean wanttangents = !r_showsurfaces.integer;
5022
5023         switch(vid.renderpath)
5024         {
5025         case RENDERPATH_GL20:
5026         case RENDERPATH_D3D9:
5027         case RENDERPATH_D3D10:
5028         case RENDERPATH_D3D11:
5029         case RENDERPATH_GLES2:
5030                 break;
5031         case RENDERPATH_GL11:
5032         case RENDERPATH_GL13:
5033         case RENDERPATH_GLES1:
5034                 wanttangents = false;
5035                 break;
5036         case RENDERPATH_SOFT:
5037                 break;
5038         }
5039
5040         if (r_shownormals.integer)
5041                 wanttangents = wantnormals = true;
5042
5043         // TODO: thread this
5044         // NOTE: R_PrepareRTLights() also caches entities
5045
5046         for (i = 0;i < r_refdef.scene.numentities;i++)
5047                 if (r_refdef.viewcache.entityvisible[i])
5048                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5049 }
5050
5051 //==================================================================================
5052
5053 extern cvar_t r_overheadsprites_pushback;
5054
5055 static void R_View_UpdateEntityLighting (void)
5056 {
5057         int i;
5058         entity_render_t *ent;
5059         vec3_t tempdiffusenormal, avg;
5060         vec_t f, fa, fd, fdd;
5061         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5062
5063         for (i = 0;i < r_refdef.scene.numentities;i++)
5064         {
5065                 ent = r_refdef.scene.entities[i];
5066
5067                 // skip unseen models
5068                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5069                         continue;
5070
5071                 // skip bsp models
5072                 if (ent->model && ent->model == cl.worldmodel)
5073                 {
5074                         // TODO: use modellight for r_ambient settings on world?
5075                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5076                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5077                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5078                         continue;
5079                 }
5080                 
5081                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5082                 {
5083                         // aleady updated by CSQC
5084                         // TODO: force modellight on BSP models in this case?
5085                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5086                 }
5087                 else
5088                 {
5089                         // fetch the lighting from the worldmodel data
5090                         VectorClear(ent->modellight_ambient);
5091                         VectorClear(ent->modellight_diffuse);
5092                         VectorClear(tempdiffusenormal);
5093                         if (ent->flags & RENDER_LIGHT)
5094                         {
5095                                 vec3_t org;
5096                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5097
5098                                 // complete lightning for lit sprites
5099                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5100                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5101                                 {
5102                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5103                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5104                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5105                                 }
5106                                 else
5107                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5108
5109                                 if(ent->flags & RENDER_EQUALIZE)
5110                                 {
5111                                         // first fix up ambient lighting...
5112                                         if(r_equalize_entities_minambient.value > 0)
5113                                         {
5114                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5115                                                 if(fd > 0)
5116                                                 {
5117                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5118                                                         if(fa < r_equalize_entities_minambient.value * fd)
5119                                                         {
5120                                                                 // solve:
5121                                                                 //   fa'/fd' = minambient
5122                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5123                                                                 //   ...
5124                                                                 //   fa' = fd' * minambient
5125                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5126                                                                 //   ...
5127                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5128                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5129                                                                 //   ...
5130                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5131                                                                 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
5132                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5133                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5134                                                         }
5135                                                 }
5136                                         }
5137
5138                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5139                                         {
5140                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5141                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5142                                                 f = fa + 0.25 * fd;
5143                                                 if(f > 0)
5144                                                 {
5145                                                         // adjust brightness and saturation to target
5146                                                         avg[0] = avg[1] = avg[2] = fa / f;
5147                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5148                                                         avg[0] = avg[1] = avg[2] = fd / f;
5149                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5150                                                 }
5151                                         }
5152                                 }
5153                         }
5154                         else // highly rare
5155                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5156                 }
5157
5158                 // move the light direction into modelspace coordinates for lighting code
5159                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5160                 if(VectorLength2(ent->modellight_lightdir) == 0)
5161                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5162                 VectorNormalize(ent->modellight_lightdir);
5163         }
5164 }
5165
5166 #define MAX_LINEOFSIGHTTRACES 64
5167
5168 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5169 {
5170         int i;
5171         vec3_t boxmins, boxmaxs;
5172         vec3_t start;
5173         vec3_t end;
5174         dp_model_t *model = r_refdef.scene.worldmodel;
5175
5176         if (!model || !model->brush.TraceLineOfSight)
5177                 return true;
5178
5179         // expand the box a little
5180         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5181         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5182         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5183         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5184         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5185         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5186
5187         // return true if eye is inside enlarged box
5188         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5189                 return true;
5190
5191         // try center
5192         VectorCopy(eye, start);
5193         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5194         if (model->brush.TraceLineOfSight(model, start, end))
5195                 return true;
5196
5197         // try various random positions
5198         for (i = 0;i < numsamples;i++)
5199         {
5200                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5201                 if (model->brush.TraceLineOfSight(model, start, end))
5202                         return true;
5203         }
5204
5205         return false;
5206 }
5207
5208
5209 static void R_View_UpdateEntityVisible (void)
5210 {
5211         int i;
5212         int renderimask;
5213         int samples;
5214         entity_render_t *ent;
5215
5216         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5217                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5218                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5219                 :                                                          RENDER_EXTERIORMODEL;
5220         if (!r_drawviewmodel.integer)
5221                 renderimask |= RENDER_VIEWMODEL;
5222         if (!r_drawexteriormodel.integer)
5223                 renderimask |= RENDER_EXTERIORMODEL;
5224         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5225         {
5226                 // worldmodel can check visibility
5227                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
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                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
5244                 }
5245         }
5246         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5247                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5248         {
5249                 for (i = 0;i < r_refdef.scene.numentities;i++)
5250                 {
5251                         if (!r_refdef.viewcache.entityvisible[i])
5252                                 continue;
5253                         ent = r_refdef.scene.entities[i];
5254                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5255                         {
5256                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5257                                 if (samples < 0)
5258                                         continue; // temp entities do pvs only
5259                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5260                                         ent->last_trace_visibility = realtime;
5261                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5262                                         r_refdef.viewcache.entityvisible[i] = 0;
5263                         }
5264                 }
5265         }
5266 }
5267
5268 /// only used if skyrendermasked, and normally returns false
5269 static int R_DrawBrushModelsSky (void)
5270 {
5271         int i, sky;
5272         entity_render_t *ent;
5273
5274         sky = false;
5275         for (i = 0;i < r_refdef.scene.numentities;i++)
5276         {
5277                 if (!r_refdef.viewcache.entityvisible[i])
5278                         continue;
5279                 ent = r_refdef.scene.entities[i];
5280                 if (!ent->model || !ent->model->DrawSky)
5281                         continue;
5282                 ent->model->DrawSky(ent);
5283                 sky = true;
5284         }
5285         return sky;
5286 }
5287
5288 static void R_DrawNoModel(entity_render_t *ent);
5289 static void R_DrawModels(void)
5290 {
5291         int i;
5292         entity_render_t *ent;
5293
5294         for (i = 0;i < r_refdef.scene.numentities;i++)
5295         {
5296                 if (!r_refdef.viewcache.entityvisible[i])
5297                         continue;
5298                 ent = r_refdef.scene.entities[i];
5299                 r_refdef.stats[r_stat_entities]++;
5300                 /*
5301                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5302                 {
5303                         vec3_t f, l, u, o;
5304                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5305                         Con_Printf("R_DrawModels\n");
5306                         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]);
5307                         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);
5308                         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);
5309                 }
5310                 */
5311                 if (ent->model && ent->model->Draw != NULL)
5312                         ent->model->Draw(ent);
5313                 else
5314                         R_DrawNoModel(ent);
5315         }
5316 }
5317
5318 static void R_DrawModelsDepth(void)
5319 {
5320         int i;
5321         entity_render_t *ent;
5322
5323         for (i = 0;i < r_refdef.scene.numentities;i++)
5324         {
5325                 if (!r_refdef.viewcache.entityvisible[i])
5326                         continue;
5327                 ent = r_refdef.scene.entities[i];
5328                 if (ent->model && ent->model->DrawDepth != NULL)
5329                         ent->model->DrawDepth(ent);
5330         }
5331 }
5332
5333 static void R_DrawModelsDebug(void)
5334 {
5335         int i;
5336         entity_render_t *ent;
5337
5338         for (i = 0;i < r_refdef.scene.numentities;i++)
5339         {
5340                 if (!r_refdef.viewcache.entityvisible[i])
5341                         continue;
5342                 ent = r_refdef.scene.entities[i];
5343                 if (ent->model && ent->model->DrawDebug != NULL)
5344                         ent->model->DrawDebug(ent);
5345         }
5346 }
5347
5348 static void R_DrawModelsAddWaterPlanes(void)
5349 {
5350         int i;
5351         entity_render_t *ent;
5352
5353         for (i = 0;i < r_refdef.scene.numentities;i++)
5354         {
5355                 if (!r_refdef.viewcache.entityvisible[i])
5356                         continue;
5357                 ent = r_refdef.scene.entities[i];
5358                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5359                         ent->model->DrawAddWaterPlanes(ent);
5360         }
5361 }
5362
5363 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}};
5364
5365 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5366 {
5367         if (r_hdr_irisadaptation.integer)
5368         {
5369                 vec3_t p;
5370                 vec3_t ambient;
5371                 vec3_t diffuse;
5372                 vec3_t diffusenormal;
5373                 vec3_t forward;
5374                 vec_t brightness = 0.0f;
5375                 vec_t goal;
5376                 vec_t current;
5377                 vec_t d;
5378                 int c;
5379                 VectorCopy(r_refdef.view.forward, forward);
5380                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5381                 {
5382                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5383                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5384                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5385                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5386                         d = DotProduct(forward, diffusenormal);
5387                         brightness += VectorLength(ambient);
5388                         if (d > 0)
5389                                 brightness += d * VectorLength(diffuse);
5390                 }
5391                 brightness *= 1.0f / c;
5392                 brightness += 0.00001f; // make sure it's never zero
5393                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5394                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5395                 current = r_hdr_irisadaptation_value.value;
5396                 if (current < goal)
5397                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5398                 else if (current > goal)
5399                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5400                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5401                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5402         }
5403         else if (r_hdr_irisadaptation_value.value != 1.0f)
5404                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5405 }
5406
5407 static void R_View_SetFrustum(const int *scissor)
5408 {
5409         int i;
5410         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5411         vec3_t forward, left, up, origin, v;
5412
5413         if(scissor)
5414         {
5415                 // flipped x coordinates (because x points left here)
5416                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5417                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5418
5419                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5420                 switch(vid.renderpath)
5421                 {
5422                         case RENDERPATH_D3D9:
5423                         case RENDERPATH_D3D10:
5424                         case RENDERPATH_D3D11:
5425                                 // non-flipped y coordinates
5426                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5427                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5428                                 break;
5429                         case RENDERPATH_SOFT:
5430                         case RENDERPATH_GL11:
5431                         case RENDERPATH_GL13:
5432                         case RENDERPATH_GL20:
5433                         case RENDERPATH_GLES1:
5434                         case RENDERPATH_GLES2:
5435                                 // non-flipped y coordinates
5436                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5437                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5438                                 break;
5439                 }
5440         }
5441
5442         // we can't trust r_refdef.view.forward and friends in reflected scenes
5443         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5444
5445 #if 0
5446         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5447         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5448         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5449         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5450         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5451         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5452         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5453         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5454         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5455         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5456         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5457         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5458 #endif
5459
5460 #if 0
5461         zNear = r_refdef.nearclip;
5462         nudge = 1.0 - 1.0 / (1<<23);
5463         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5464         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5465         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5466         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5467         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5468         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5469         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5470         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5471 #endif
5472
5473
5474
5475 #if 0
5476         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5477         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5478         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5479         r_refdef.view.frustum[0].dist = m[15] - m[12];
5480
5481         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5482         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5483         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5484         r_refdef.view.frustum[1].dist = m[15] + m[12];
5485
5486         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5487         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5488         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5489         r_refdef.view.frustum[2].dist = m[15] - m[13];
5490
5491         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5492         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5493         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5494         r_refdef.view.frustum[3].dist = m[15] + m[13];
5495
5496         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5497         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5498         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5499         r_refdef.view.frustum[4].dist = m[15] - m[14];
5500
5501         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5502         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5503         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5504         r_refdef.view.frustum[5].dist = m[15] + m[14];
5505 #endif
5506
5507         if (r_refdef.view.useperspective)
5508         {
5509                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5510                 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]);
5511                 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]);
5512                 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]);
5513                 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]);
5514
5515                 // then the normals from the corners relative to origin
5516                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5517                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5518                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5519                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5520
5521                 // in a NORMAL view, forward cross left == up
5522                 // in a REFLECTED view, forward cross left == down
5523                 // so our cross products above need to be adjusted for a left handed coordinate system
5524                 CrossProduct(forward, left, v);
5525                 if(DotProduct(v, up) < 0)
5526                 {
5527                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5528                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5529                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5530                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5531                 }
5532
5533                 // Leaving those out was a mistake, those were in the old code, and they
5534                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5535                 // I couldn't reproduce it after adding those normalizations. --blub
5536                 VectorNormalize(r_refdef.view.frustum[0].normal);
5537                 VectorNormalize(r_refdef.view.frustum[1].normal);
5538                 VectorNormalize(r_refdef.view.frustum[2].normal);
5539                 VectorNormalize(r_refdef.view.frustum[3].normal);
5540
5541                 // make the corners absolute
5542                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5543                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5544                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5545                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5546
5547                 // one more normal
5548                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5549
5550                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5551                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5552                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5553                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5554                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5555         }
5556         else
5557         {
5558                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5559                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5560                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5561                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5562                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5563                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5564                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5565                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5566                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5567                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5568         }
5569         r_refdef.view.numfrustumplanes = 5;
5570
5571         if (r_refdef.view.useclipplane)
5572         {
5573                 r_refdef.view.numfrustumplanes = 6;
5574                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5575         }
5576
5577         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5578                 PlaneClassify(r_refdef.view.frustum + i);
5579
5580         // LordHavoc: note to all quake engine coders, Quake had a special case
5581         // for 90 degrees which assumed a square view (wrong), so I removed it,
5582         // Quake2 has it disabled as well.
5583
5584         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5585         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5586         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5587         //PlaneClassify(&frustum[0]);
5588
5589         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5590         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5591         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5592         //PlaneClassify(&frustum[1]);
5593
5594         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5595         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5596         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5597         //PlaneClassify(&frustum[2]);
5598
5599         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5600         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5601         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5602         //PlaneClassify(&frustum[3]);
5603
5604         // nearclip plane
5605         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5606         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5607         //PlaneClassify(&frustum[4]);
5608 }
5609
5610 static void R_View_UpdateWithScissor(const int *myscissor)
5611 {
5612         R_Main_ResizeViewCache();
5613         R_View_SetFrustum(myscissor);
5614         R_View_WorldVisibility(r_refdef.view.useclipplane);
5615         R_View_UpdateEntityVisible();
5616         R_View_UpdateEntityLighting();
5617 }
5618
5619 static void R_View_Update(void)
5620 {
5621         R_Main_ResizeViewCache();
5622         R_View_SetFrustum(NULL);
5623         R_View_WorldVisibility(r_refdef.view.useclipplane);
5624         R_View_UpdateEntityVisible();
5625         R_View_UpdateEntityLighting();
5626 }
5627
5628 float viewscalefpsadjusted = 1.0f;
5629
5630 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5631 {
5632         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5633         scale = bound(0.03125f, scale, 1.0f);
5634         *outwidth = (int)ceil(width * scale);
5635         *outheight = (int)ceil(height * scale);
5636 }
5637
5638 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5639 {
5640         const float *customclipplane = NULL;
5641         float plane[4];
5642         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5643         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5644         {
5645                 // LordHavoc: couldn't figure out how to make this approach the
5646                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5647                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5648                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5649                         dist = r_refdef.view.clipplane.dist;
5650                 plane[0] = r_refdef.view.clipplane.normal[0];
5651                 plane[1] = r_refdef.view.clipplane.normal[1];
5652                 plane[2] = r_refdef.view.clipplane.normal[2];
5653                 plane[3] = -dist;
5654                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5655         }
5656
5657         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5658         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5659
5660         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5661         if (!r_refdef.view.useperspective)
5662                 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);
5663         else if (vid.stencil && r_useinfinitefarclip.integer)
5664                 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);
5665         else
5666                 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);
5667         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5668         R_SetViewport(&r_refdef.view.viewport);
5669         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5670         {
5671                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5672                 float screenplane[4];
5673                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5674                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5675                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5676                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5677                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5678         }
5679 }
5680
5681 void R_EntityMatrix(const matrix4x4_t *matrix)
5682 {
5683         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5684         {
5685                 gl_modelmatrixchanged = false;
5686                 gl_modelmatrix = *matrix;
5687                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5688                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5689                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5690                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5691                 CHECKGLERROR
5692                 switch(vid.renderpath)
5693                 {
5694                 case RENDERPATH_D3D9:
5695 #ifdef SUPPORTD3D
5696                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5697                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5698 #endif
5699                         break;
5700                 case RENDERPATH_D3D10:
5701                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5702                         break;
5703                 case RENDERPATH_D3D11:
5704                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5705                         break;
5706                 case RENDERPATH_GL11:
5707                 case RENDERPATH_GL13:
5708                 case RENDERPATH_GLES1:
5709 #ifndef USE_GLES2
5710                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5711 #endif
5712                         break;
5713                 case RENDERPATH_SOFT:
5714                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5715                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5716                         break;
5717                 case RENDERPATH_GL20:
5718                 case RENDERPATH_GLES2:
5719                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5720                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5721                         break;
5722                 }
5723         }
5724 }
5725
5726 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5727 {
5728         r_viewport_t viewport;
5729
5730         CHECKGLERROR
5731
5732         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5733         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);
5734         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5735         R_SetViewport(&viewport);
5736         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5737         GL_Color(1, 1, 1, 1);
5738         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5739         GL_BlendFunc(GL_ONE, GL_ZERO);
5740         GL_ScissorTest(false);
5741         GL_DepthMask(false);
5742         GL_DepthRange(0, 1);
5743         GL_DepthTest(false);
5744         GL_DepthFunc(GL_LEQUAL);
5745         R_EntityMatrix(&identitymatrix);
5746         R_Mesh_ResetTextureState();
5747         GL_PolygonOffset(0, 0);
5748         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5749         switch(vid.renderpath)
5750         {
5751         case RENDERPATH_GL11:
5752         case RENDERPATH_GL13:
5753         case RENDERPATH_GL20:
5754         case RENDERPATH_GLES1:
5755         case RENDERPATH_GLES2:
5756                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5757                 break;
5758         case RENDERPATH_D3D9:
5759         case RENDERPATH_D3D10:
5760         case RENDERPATH_D3D11:
5761         case RENDERPATH_SOFT:
5762                 break;
5763         }
5764         GL_CullFace(GL_NONE);
5765
5766         CHECKGLERROR
5767 }
5768
5769 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5770 {
5771         DrawQ_Finish();
5772
5773         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5774 }
5775
5776 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5777 {
5778         DrawQ_Finish();
5779
5780         R_SetupView(true, fbo, depthtexture, colortexture);
5781         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5782         GL_Color(1, 1, 1, 1);
5783         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5784         GL_BlendFunc(GL_ONE, GL_ZERO);
5785         GL_ScissorTest(true);
5786         GL_DepthMask(true);
5787         GL_DepthRange(0, 1);
5788         GL_DepthTest(true);
5789         GL_DepthFunc(GL_LEQUAL);
5790         R_EntityMatrix(&identitymatrix);
5791         R_Mesh_ResetTextureState();
5792         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5793         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5794         switch(vid.renderpath)
5795         {
5796         case RENDERPATH_GL11:
5797         case RENDERPATH_GL13:
5798         case RENDERPATH_GL20:
5799         case RENDERPATH_GLES1:
5800         case RENDERPATH_GLES2:
5801                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5802                 break;
5803         case RENDERPATH_D3D9:
5804         case RENDERPATH_D3D10:
5805         case RENDERPATH_D3D11:
5806         case RENDERPATH_SOFT:
5807                 break;
5808         }
5809         GL_CullFace(r_refdef.view.cullface_back);
5810 }
5811
5812 /*
5813 ================
5814 R_RenderView_UpdateViewVectors
5815 ================
5816 */
5817 void R_RenderView_UpdateViewVectors(void)
5818 {
5819         // break apart the view matrix into vectors for various purposes
5820         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5821         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5822         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5823         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5824         // make an inverted copy of the view matrix for tracking sprites
5825         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5826 }
5827
5828 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5829 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5830
5831 static void R_Water_StartFrame(void)
5832 {
5833         int i;
5834         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5835         r_waterstate_waterplane_t *p;
5836         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;
5837
5838         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5839                 return;
5840
5841         switch(vid.renderpath)
5842         {
5843         case RENDERPATH_GL20:
5844         case RENDERPATH_D3D9:
5845         case RENDERPATH_D3D10:
5846         case RENDERPATH_D3D11:
5847         case RENDERPATH_SOFT:
5848         case RENDERPATH_GLES2:
5849                 break;
5850         case RENDERPATH_GL11:
5851         case RENDERPATH_GL13:
5852         case RENDERPATH_GLES1:
5853                 return;
5854         }
5855
5856         // set waterwidth and waterheight to the water resolution that will be
5857         // used (often less than the screen resolution for faster rendering)
5858         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5859
5860         // calculate desired texture sizes
5861         // can't use water if the card does not support the texture size
5862         if (!r_water.integer || r_showsurfaces.integer)
5863                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5864         else if (vid.support.arb_texture_non_power_of_two)
5865         {
5866                 texturewidth = waterwidth;
5867                 textureheight = waterheight;
5868                 camerawidth = waterwidth;
5869                 cameraheight = waterheight;
5870         }
5871         else
5872         {
5873                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5874                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5875                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5876                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5877         }
5878
5879         // allocate textures as needed
5880         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))
5881         {
5882                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5883                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5884                 {
5885                         if (p->texture_refraction)
5886                                 R_FreeTexture(p->texture_refraction);
5887                         p->texture_refraction = NULL;
5888                         if (p->fbo_refraction)
5889                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5890                         p->fbo_refraction = 0;
5891                         if (p->texture_reflection)
5892                                 R_FreeTexture(p->texture_reflection);
5893                         p->texture_reflection = NULL;
5894                         if (p->fbo_reflection)
5895                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5896                         p->fbo_reflection = 0;
5897                         if (p->texture_camera)
5898                                 R_FreeTexture(p->texture_camera);
5899                         p->texture_camera = NULL;
5900                         if (p->fbo_camera)
5901                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5902                         p->fbo_camera = 0;
5903                 }
5904                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5905                 r_fb.water.texturewidth = texturewidth;
5906                 r_fb.water.textureheight = textureheight;
5907                 r_fb.water.camerawidth = camerawidth;
5908                 r_fb.water.cameraheight = cameraheight;
5909         }
5910
5911         if (r_fb.water.texturewidth)
5912         {
5913                 int scaledwidth, scaledheight;
5914
5915                 r_fb.water.enabled = true;
5916
5917                 // water resolution is usually reduced
5918                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5919                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5920                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5921
5922                 // set up variables that will be used in shader setup
5923                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5924                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5925                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5926                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5927         }
5928
5929         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5930         r_fb.water.numwaterplanes = 0;
5931 }
5932
5933 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5934 {
5935         int planeindex, bestplaneindex, vertexindex;
5936         vec3_t mins, maxs, normal, center, v, n;
5937         vec_t planescore, bestplanescore;
5938         mplane_t plane;
5939         r_waterstate_waterplane_t *p;
5940         texture_t *t = R_GetCurrentTexture(surface->texture);
5941
5942         rsurface.texture = t;
5943         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5944         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5945         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5946                 return;
5947         // average the vertex normals, find the surface bounds (after deformvertexes)
5948         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5949         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5950         VectorCopy(n, normal);
5951         VectorCopy(v, mins);
5952         VectorCopy(v, maxs);
5953         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5954         {
5955                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5956                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5957                 VectorAdd(normal, n, normal);
5958                 mins[0] = min(mins[0], v[0]);
5959                 mins[1] = min(mins[1], v[1]);
5960                 mins[2] = min(mins[2], v[2]);
5961                 maxs[0] = max(maxs[0], v[0]);
5962                 maxs[1] = max(maxs[1], v[1]);
5963                 maxs[2] = max(maxs[2], v[2]);
5964         }
5965         VectorNormalize(normal);
5966         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5967
5968         VectorCopy(normal, plane.normal);
5969         VectorNormalize(plane.normal);
5970         plane.dist = DotProduct(center, plane.normal);
5971         PlaneClassify(&plane);
5972         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5973         {
5974                 // skip backfaces (except if nocullface is set)
5975 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5976 //                      return;
5977                 VectorNegate(plane.normal, plane.normal);
5978                 plane.dist *= -1;
5979                 PlaneClassify(&plane);
5980         }
5981
5982
5983         // find a matching plane if there is one
5984         bestplaneindex = -1;
5985         bestplanescore = 1048576.0f;
5986         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5987         {
5988                 if(p->camera_entity == t->camera_entity)
5989                 {
5990                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5991                         if (bestplaneindex < 0 || bestplanescore > planescore)
5992                         {
5993                                 bestplaneindex = planeindex;
5994                                 bestplanescore = planescore;
5995                         }
5996                 }
5997         }
5998         planeindex = bestplaneindex;
5999         p = r_fb.water.waterplanes + planeindex;
6000
6001         // if this surface does not fit any known plane rendered this frame, add one
6002         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6003         {
6004                 // store the new plane
6005                 planeindex = r_fb.water.numwaterplanes++;
6006                 p = r_fb.water.waterplanes + planeindex;
6007                 p->plane = plane;
6008                 // clear materialflags and pvs
6009                 p->materialflags = 0;
6010                 p->pvsvalid = false;
6011                 p->camera_entity = t->camera_entity;
6012                 VectorCopy(mins, p->mins);
6013                 VectorCopy(maxs, p->maxs);
6014         }
6015         else
6016         {
6017                 // merge mins/maxs when we're adding this surface to the plane
6018                 p->mins[0] = min(p->mins[0], mins[0]);
6019                 p->mins[1] = min(p->mins[1], mins[1]);
6020                 p->mins[2] = min(p->mins[2], mins[2]);
6021                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6022                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6023                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6024         }
6025         // merge this surface's materialflags into the waterplane
6026         p->materialflags |= t->currentmaterialflags;
6027         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6028         {
6029                 // merge this surface's PVS into the waterplane
6030                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6031                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6032                 {
6033                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6034                         p->pvsvalid = true;
6035                 }
6036         }
6037 }
6038
6039 extern cvar_t r_drawparticles;
6040 extern cvar_t r_drawdecals;
6041
6042 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6043 {
6044         int myscissor[4];
6045         r_refdef_view_t originalview;
6046         r_refdef_view_t myview;
6047         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;
6048         r_waterstate_waterplane_t *p;
6049         vec3_t visorigin;
6050         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;
6051         char vabuf[1024];
6052
6053         originalview = r_refdef.view;
6054
6055         // lowquality hack, temporarily shut down some cvars and restore afterwards
6056         qualityreduction = r_water_lowquality.integer;
6057         if (qualityreduction > 0)
6058         {
6059                 if (qualityreduction >= 1)
6060                 {
6061                         old_r_shadows = r_shadows.integer;
6062                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6063                         old_r_dlight = r_shadow_realtime_dlight.integer;
6064                         Cvar_SetValueQuick(&r_shadows, 0);
6065                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6066                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6067                 }
6068                 if (qualityreduction >= 2)
6069                 {
6070                         old_r_dynamic = r_dynamic.integer;
6071                         old_r_particles = r_drawparticles.integer;
6072                         old_r_decals = r_drawdecals.integer;
6073                         Cvar_SetValueQuick(&r_dynamic, 0);
6074                         Cvar_SetValueQuick(&r_drawparticles, 0);
6075                         Cvar_SetValueQuick(&r_drawdecals, 0);
6076                 }
6077         }
6078
6079         // make sure enough textures are allocated
6080         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6081         {
6082                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6083                 {
6084                         if (!p->texture_refraction)
6085                                 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);
6086                         if (!p->texture_refraction)
6087                                 goto error;
6088                         if (usewaterfbo)
6089                         {
6090                                 if (r_fb.water.depthtexture == NULL)
6091                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6092                                 if (p->fbo_refraction == 0)
6093                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6094                         }
6095                 }
6096                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6097                 {
6098                         if (!p->texture_camera)
6099                                 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);
6100                         if (!p->texture_camera)
6101                                 goto error;
6102                         if (usewaterfbo)
6103                         {
6104                                 if (r_fb.water.depthtexture == NULL)
6105                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6106                                 if (p->fbo_camera == 0)
6107                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6108                         }
6109                 }
6110
6111                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6112                 {
6113                         if (!p->texture_reflection)
6114                                 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);
6115                         if (!p->texture_reflection)
6116                                 goto error;
6117                         if (usewaterfbo)
6118                         {
6119                                 if (r_fb.water.depthtexture == NULL)
6120                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6121                                 if (p->fbo_reflection == 0)
6122                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6123                         }
6124                 }
6125         }
6126
6127         // render views
6128         r_refdef.view = originalview;
6129         r_refdef.view.showdebug = false;
6130         r_refdef.view.width = r_fb.water.waterwidth;
6131         r_refdef.view.height = r_fb.water.waterheight;
6132         r_refdef.view.useclipplane = true;
6133         myview = r_refdef.view;
6134         r_fb.water.renderingscene = true;
6135         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6136         {
6137                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6138                 {
6139                         r_refdef.view = myview;
6140                         if(r_water_scissormode.integer)
6141                         {
6142                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6143                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6144                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6145                         }
6146
6147                         // render reflected scene and copy into texture
6148                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6149                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6150                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6151                         r_refdef.view.clipplane = p->plane;
6152                         // reverse the cullface settings for this render
6153                         r_refdef.view.cullface_front = GL_FRONT;
6154                         r_refdef.view.cullface_back = GL_BACK;
6155                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6156                         {
6157                                 r_refdef.view.usecustompvs = true;
6158                                 if (p->pvsvalid)
6159                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6160                                 else
6161                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6162                         }
6163
6164                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6165                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6166                         R_ClearScreen(r_refdef.fogenabled);
6167                         if(r_water_scissormode.integer & 2)
6168                                 R_View_UpdateWithScissor(myscissor);
6169                         else
6170                                 R_View_Update();
6171                         R_AnimCache_CacheVisibleEntities();
6172                         if(r_water_scissormode.integer & 1)
6173                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6174                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6175
6176                         if (!p->fbo_reflection)
6177                                 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);
6178                         r_fb.water.hideplayer = false;
6179                 }
6180
6181                 // render the normal view scene and copy into texture
6182                 // (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)
6183                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6184                 {
6185                         r_refdef.view = myview;
6186                         if(r_water_scissormode.integer)
6187                         {
6188                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6189                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6190                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6191                         }
6192
6193                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6194
6195                         r_refdef.view.clipplane = p->plane;
6196                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6197                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6198
6199                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6200                         {
6201                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6202                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6203                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6204                                 R_RenderView_UpdateViewVectors();
6205                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6206                                 {
6207                                         r_refdef.view.usecustompvs = true;
6208                                         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);
6209                                 }
6210                         }
6211
6212                         PlaneClassify(&r_refdef.view.clipplane);
6213
6214                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6215                         R_ClearScreen(r_refdef.fogenabled);
6216                         if(r_water_scissormode.integer & 2)
6217                                 R_View_UpdateWithScissor(myscissor);
6218                         else
6219                                 R_View_Update();
6220                         R_AnimCache_CacheVisibleEntities();
6221                         if(r_water_scissormode.integer & 1)
6222                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6223                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6224
6225                         if (!p->fbo_refraction)
6226                                 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);
6227                         r_fb.water.hideplayer = false;
6228                 }
6229                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6230                 {
6231                         r_refdef.view = myview;
6232
6233                         r_refdef.view.clipplane = p->plane;
6234                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6235                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6236
6237                         r_refdef.view.width = r_fb.water.camerawidth;
6238                         r_refdef.view.height = r_fb.water.cameraheight;
6239                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6240                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6241                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6242                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6243
6244                         if(p->camera_entity)
6245                         {
6246                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6247                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6248                         }
6249
6250                         // note: all of the view is used for displaying... so
6251                         // there is no use in scissoring
6252
6253                         // reverse the cullface settings for this render
6254                         r_refdef.view.cullface_front = GL_FRONT;
6255                         r_refdef.view.cullface_back = GL_BACK;
6256                         // also reverse the view matrix
6257                         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
6258                         R_RenderView_UpdateViewVectors();
6259                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6260                         {
6261                                 r_refdef.view.usecustompvs = true;
6262                                 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);
6263                         }
6264                         
6265                         // camera needs no clipplane
6266                         r_refdef.view.useclipplane = false;
6267
6268                         PlaneClassify(&r_refdef.view.clipplane);
6269
6270                         r_fb.water.hideplayer = false;
6271
6272                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6273                         R_ClearScreen(r_refdef.fogenabled);
6274                         R_View_Update();
6275                         R_AnimCache_CacheVisibleEntities();
6276                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6277
6278                         if (!p->fbo_camera)
6279                                 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);
6280                         r_fb.water.hideplayer = false;
6281                 }
6282
6283         }
6284         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6285         r_fb.water.renderingscene = false;
6286         r_refdef.view = originalview;
6287         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6288         if (!r_fb.water.depthtexture)
6289                 R_ClearScreen(r_refdef.fogenabled);
6290         R_View_Update();
6291         R_AnimCache_CacheVisibleEntities();
6292         goto finish;
6293 error:
6294         r_refdef.view = originalview;
6295         r_fb.water.renderingscene = false;
6296         Cvar_SetValueQuick(&r_water, 0);
6297         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6298 finish:
6299         // lowquality hack, restore cvars
6300         if (qualityreduction > 0)
6301         {
6302                 if (qualityreduction >= 1)
6303                 {
6304                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6305                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6306                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6307                 }
6308                 if (qualityreduction >= 2)
6309                 {
6310                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6311                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6312                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6313                 }
6314         }
6315 }
6316
6317 static void R_Bloom_StartFrame(void)
6318 {
6319         int i;
6320         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6321         int viewwidth, viewheight;
6322         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6323         textype_t textype = TEXTYPE_COLORBUFFER;
6324
6325         switch (vid.renderpath)
6326         {
6327         case RENDERPATH_GL20:
6328                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6329                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6330                 {
6331                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6332                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6333                 }
6334                 break;
6335         case RENDERPATH_GL11:
6336         case RENDERPATH_GL13:
6337         case RENDERPATH_GLES1:
6338         case RENDERPATH_GLES2:
6339         case RENDERPATH_D3D9:
6340         case RENDERPATH_D3D10:
6341         case RENDERPATH_D3D11:
6342                 r_fb.usedepthtextures = false;
6343                 break;
6344         case RENDERPATH_SOFT:
6345                 r_fb.usedepthtextures = true;
6346                 break;
6347         }
6348
6349         if (r_viewscale_fpsscaling.integer)
6350         {
6351                 double actualframetime;
6352                 double targetframetime;
6353                 double adjust;
6354                 actualframetime = r_refdef.lastdrawscreentime;
6355                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6356                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6357                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6358                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6359                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6360                 viewscalefpsadjusted += adjust;
6361                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6362         }
6363         else
6364                 viewscalefpsadjusted = 1.0f;
6365
6366         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6367
6368         switch(vid.renderpath)
6369         {
6370         case RENDERPATH_GL20:
6371         case RENDERPATH_D3D9:
6372         case RENDERPATH_D3D10:
6373         case RENDERPATH_D3D11:
6374         case RENDERPATH_SOFT:
6375         case RENDERPATH_GLES2:
6376                 break;
6377         case RENDERPATH_GL11:
6378         case RENDERPATH_GL13:
6379         case RENDERPATH_GLES1:
6380                 return;
6381         }
6382
6383         // set bloomwidth and bloomheight to the bloom resolution that will be
6384         // used (often less than the screen resolution for faster rendering)
6385         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6386         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6387         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6388         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6389         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6390
6391         // calculate desired texture sizes
6392         if (vid.support.arb_texture_non_power_of_two)
6393         {
6394                 screentexturewidth = vid.width;
6395                 screentextureheight = vid.height;
6396                 bloomtexturewidth = r_fb.bloomwidth;
6397                 bloomtextureheight = r_fb.bloomheight;
6398         }
6399         else
6400         {
6401                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6402                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6403                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6404                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6405         }
6406
6407         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))
6408         {
6409                 Cvar_SetValueQuick(&r_bloom, 0);
6410                 Cvar_SetValueQuick(&r_motionblur, 0);
6411                 Cvar_SetValueQuick(&r_damageblur, 0);
6412         }
6413
6414         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6415          && !r_bloom.integer
6416          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6417          && !useviewfbo
6418          && r_viewscale.value == 1.0f
6419          && !r_viewscale_fpsscaling.integer)
6420                 screentexturewidth = screentextureheight = 0;
6421         if (!r_bloom.integer)
6422                 bloomtexturewidth = bloomtextureheight = 0;
6423
6424         // allocate textures as needed
6425         if (r_fb.screentexturewidth != screentexturewidth
6426          || r_fb.screentextureheight != screentextureheight
6427          || r_fb.bloomtexturewidth != bloomtexturewidth
6428          || r_fb.bloomtextureheight != bloomtextureheight
6429          || r_fb.textype != textype
6430          || useviewfbo != (r_fb.fbo != 0))
6431         {
6432                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6433                 {
6434                         if (r_fb.bloomtexture[i])
6435                                 R_FreeTexture(r_fb.bloomtexture[i]);
6436                         r_fb.bloomtexture[i] = NULL;
6437
6438                         if (r_fb.bloomfbo[i])
6439                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6440                         r_fb.bloomfbo[i] = 0;
6441                 }
6442
6443                 if (r_fb.fbo)
6444                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6445                 r_fb.fbo = 0;
6446
6447                 if (r_fb.colortexture)
6448                         R_FreeTexture(r_fb.colortexture);
6449                 r_fb.colortexture = NULL;
6450
6451                 if (r_fb.depthtexture)
6452                         R_FreeTexture(r_fb.depthtexture);
6453                 r_fb.depthtexture = NULL;
6454
6455                 if (r_fb.ghosttexture)
6456                         R_FreeTexture(r_fb.ghosttexture);
6457                 r_fb.ghosttexture = NULL;
6458
6459                 r_fb.screentexturewidth = screentexturewidth;
6460                 r_fb.screentextureheight = screentextureheight;
6461                 r_fb.bloomtexturewidth = bloomtexturewidth;
6462                 r_fb.bloomtextureheight = bloomtextureheight;
6463                 r_fb.textype = textype;
6464
6465                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6466                 {
6467                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6468                                 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);
6469                         r_fb.ghosttexture_valid = false;
6470                         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);
6471                         if (useviewfbo)
6472                         {
6473                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6474                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6475                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6476                         }
6477                 }
6478
6479                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6480                 {
6481                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6482                         {
6483                                 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);
6484                                 if (useviewfbo)
6485                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6486                         }
6487                 }
6488         }
6489
6490         // bloom texture is a different resolution
6491         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6492         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6493         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6494         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6495         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6496
6497         // set up a texcoord array for the full resolution screen image
6498         // (we have to keep this around to copy back during final render)
6499         r_fb.screentexcoord2f[0] = 0;
6500         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6501         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6502         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6503         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6504         r_fb.screentexcoord2f[5] = 0;
6505         r_fb.screentexcoord2f[6] = 0;
6506         r_fb.screentexcoord2f[7] = 0;
6507
6508         if(r_fb.fbo) 
6509         {
6510                 for (i = 1;i < 8;i += 2)
6511                 {
6512                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6513                 }
6514         }
6515
6516         // set up a texcoord array for the reduced resolution bloom image
6517         // (which will be additive blended over the screen image)
6518         r_fb.bloomtexcoord2f[0] = 0;
6519         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6520         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6521         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6522         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6523         r_fb.bloomtexcoord2f[5] = 0;
6524         r_fb.bloomtexcoord2f[6] = 0;
6525         r_fb.bloomtexcoord2f[7] = 0;
6526
6527         switch(vid.renderpath)
6528         {
6529         case RENDERPATH_GL11:
6530         case RENDERPATH_GL13:
6531         case RENDERPATH_GL20:
6532         case RENDERPATH_SOFT:
6533         case RENDERPATH_GLES1:
6534         case RENDERPATH_GLES2:
6535                 break;
6536         case RENDERPATH_D3D9:
6537         case RENDERPATH_D3D10:
6538         case RENDERPATH_D3D11:
6539                 for (i = 0;i < 4;i++)
6540                 {
6541                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6542                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6543                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6544                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6545                 }
6546                 break;
6547         }
6548
6549         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6550
6551         if (r_fb.fbo)
6552                 r_refdef.view.clear = true;
6553 }
6554
6555 static void R_Bloom_MakeTexture(void)
6556 {
6557         int x, range, dir;
6558         float xoffset, yoffset, r, brighten;
6559         rtexture_t *intex;
6560         float colorscale = r_bloom_colorscale.value;
6561
6562         r_refdef.stats[r_stat_bloom]++;
6563     
6564 #if 0
6565     // this copy is unnecessary since it happens in R_BlendView already
6566         if (!r_fb.fbo)
6567         {
6568                 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);
6569                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6570         }
6571 #endif
6572
6573         // scale down screen texture to the bloom texture size
6574         CHECKGLERROR
6575         r_fb.bloomindex = 0;
6576         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6577         R_SetViewport(&r_fb.bloomviewport);
6578         GL_DepthTest(false);
6579         GL_BlendFunc(GL_ONE, GL_ZERO);
6580         GL_Color(colorscale, colorscale, colorscale, 1);
6581         // 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...
6582         switch(vid.renderpath)
6583         {
6584         case RENDERPATH_GL11:
6585         case RENDERPATH_GL13:
6586         case RENDERPATH_GL20:
6587         case RENDERPATH_GLES1:
6588         case RENDERPATH_GLES2:
6589         case RENDERPATH_SOFT:
6590                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6591                 break;
6592         case RENDERPATH_D3D9:
6593         case RENDERPATH_D3D10:
6594         case RENDERPATH_D3D11:
6595                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6596                 break;
6597         }
6598         // TODO: do boxfilter scale-down in shader?
6599         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6600         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6601         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6602
6603         // we now have a properly scaled bloom image
6604         if (!r_fb.bloomfbo[r_fb.bloomindex])
6605         {
6606                 // copy it into the bloom texture
6607                 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);
6608                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6609         }
6610
6611         // multiply bloom image by itself as many times as desired
6612         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6613         {
6614                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6615                 r_fb.bloomindex ^= 1;
6616                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6617                 x *= 2;
6618                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6619                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6620                 {
6621                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6622                         GL_Color(r,r,r,1); // apply fix factor
6623                 }
6624                 else
6625                 {
6626                         if(x <= 2)
6627                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6628                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6629                         GL_Color(1,1,1,1); // no fix factor supported here
6630                 }
6631                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6632                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6633                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6634                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6635
6636                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6637                 {
6638                         // copy the darkened image to a texture
6639                         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);
6640                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6641                 }
6642         }
6643
6644         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6645         brighten = r_bloom_brighten.value;
6646         brighten = sqrt(brighten);
6647         if(range >= 1)
6648                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6649
6650         for (dir = 0;dir < 2;dir++)
6651         {
6652                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6653                 r_fb.bloomindex ^= 1;
6654                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6655                 // blend on at multiple vertical offsets to achieve a vertical blur
6656                 // TODO: do offset blends using GLSL
6657                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6658                 GL_BlendFunc(GL_ONE, GL_ZERO);
6659                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6660                 for (x = -range;x <= range;x++)
6661                 {
6662                         if (!dir){xoffset = 0;yoffset = x;}
6663                         else {xoffset = x;yoffset = 0;}
6664                         xoffset /= (float)r_fb.bloomtexturewidth;
6665                         yoffset /= (float)r_fb.bloomtextureheight;
6666                         // compute a texcoord array with the specified x and y offset
6667                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6668                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6669                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6670                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6671                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6672                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6673                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6674                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6675                         // this r value looks like a 'dot' particle, fading sharply to
6676                         // black at the edges
6677                         // (probably not realistic but looks good enough)
6678                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6679                         //r = brighten/(range*2+1);
6680                         r = brighten / (range * 2 + 1);
6681                         if(range >= 1)
6682                                 r *= (1 - x*x/(float)(range*range));
6683                         GL_Color(r, r, r, 1);
6684                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6685                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6686                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6687                         GL_BlendFunc(GL_ONE, GL_ONE);
6688                 }
6689
6690                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6691                 {
6692                         // copy the vertically or horizontally blurred bloom view to a texture
6693                         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);
6694                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6695                 }
6696         }
6697 }
6698
6699 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6700 {
6701         unsigned int permutation;
6702         float uservecs[4][4];
6703
6704         R_EntityMatrix(&identitymatrix);
6705
6706         switch (vid.renderpath)
6707         {
6708         case RENDERPATH_GL20:
6709         case RENDERPATH_D3D9:
6710         case RENDERPATH_D3D10:
6711         case RENDERPATH_D3D11:
6712         case RENDERPATH_SOFT:
6713         case RENDERPATH_GLES2:
6714                 permutation =
6715                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6716                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6717                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6718                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6719                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6720
6721                 if (r_fb.colortexture)
6722                 {
6723                         if (!r_fb.fbo)
6724                         {
6725                                 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);
6726                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6727                         }
6728
6729                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6730                         {
6731                                 // declare variables
6732                                 float blur_factor, blur_mouseaccel, blur_velocity;
6733                                 static float blur_average; 
6734                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6735
6736                                 // set a goal for the factoring
6737                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6738                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6739                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6740                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6741                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6742                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6743
6744                                 // from the goal, pick an averaged value between goal and last value
6745                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6746                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6747
6748                                 // enforce minimum amount of blur 
6749                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6750
6751                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6752
6753                                 // calculate values into a standard alpha
6754                                 cl.motionbluralpha = 1 - exp(-
6755                                                 (
6756                                                  (r_motionblur.value * blur_factor / 80)
6757                                                  +
6758                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6759                                                 )
6760                                                 /
6761                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6762                                           );
6763
6764                                 // randomization for the blur value to combat persistent ghosting
6765                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6766                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6767
6768                                 // apply the blur
6769                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6770                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6771                                 {
6772                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6773                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6774                                         switch(vid.renderpath)
6775                                         {
6776                                         case RENDERPATH_GL11:
6777                                         case RENDERPATH_GL13:
6778                                         case RENDERPATH_GL20:
6779                                         case RENDERPATH_GLES1:
6780                                         case RENDERPATH_GLES2:
6781                                         case RENDERPATH_SOFT:
6782                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6783                                                 break;
6784                                         case RENDERPATH_D3D9:
6785                                         case RENDERPATH_D3D10:
6786                                         case RENDERPATH_D3D11:
6787                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6788                                                 break;
6789                                         }
6790                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6791                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6792                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6793                                 }
6794
6795                                 // updates old view angles for next pass
6796                                 VectorCopy(cl.viewangles, blur_oldangles);
6797
6798                                 // copy view into the ghost texture
6799                                 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);
6800                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6801                                 r_fb.ghosttexture_valid = true;
6802                         }
6803                 }
6804                 else
6805                 {
6806                         // no r_fb.colortexture means we're rendering to the real fb
6807                         // we may still have to do view tint...
6808                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6809                         {
6810                                 // apply a color tint to the whole view
6811                                 R_ResetViewRendering2D(0, NULL, NULL);
6812                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6813                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6814                                 R_SetupShader_Generic_NoTexture(false, true);
6815                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6816                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6817                         }
6818                         break; // no screen processing, no bloom, skip it
6819                 }
6820
6821                 if (r_fb.bloomtexture[0])
6822                 {
6823                         // make the bloom texture
6824                         R_Bloom_MakeTexture();
6825                 }
6826
6827 #if _MSC_VER >= 1400
6828 #define sscanf sscanf_s
6829 #endif
6830                 memset(uservecs, 0, sizeof(uservecs));
6831                 if (r_glsl_postprocess_uservec1_enable.integer)
6832                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6833                 if (r_glsl_postprocess_uservec2_enable.integer)
6834                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6835                 if (r_glsl_postprocess_uservec3_enable.integer)
6836                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6837                 if (r_glsl_postprocess_uservec4_enable.integer)
6838                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6839
6840                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6841                 GL_Color(1, 1, 1, 1);
6842                 GL_BlendFunc(GL_ONE, GL_ZERO);
6843
6844                 switch(vid.renderpath)
6845                 {
6846                 case RENDERPATH_GL20:
6847                 case RENDERPATH_GLES2:
6848                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6849                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6850                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6851                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6852                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6853                         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]);
6854                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6855                         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]);
6856                         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]);
6857                         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]);
6858                         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]);
6859                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6860                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6861                         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);
6862                         break;
6863                 case RENDERPATH_D3D9:
6864 #ifdef SUPPORTD3D
6865                         // 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...
6866                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6867                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6868                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6869                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6870                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6871                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6872                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6873                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6874                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6875                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6876                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6877                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6878                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6879                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6880 #endif
6881                         break;
6882                 case RENDERPATH_D3D10:
6883                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6884                         break;
6885                 case RENDERPATH_D3D11:
6886                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6887                         break;
6888                 case RENDERPATH_SOFT:
6889                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6890                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6891                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6892                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6893                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6894                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6895                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6896                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6897                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6898                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6899                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6900                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6901                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6902                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6903                         break;
6904                 default:
6905                         break;
6906                 }
6907                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6908                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6909                 break;
6910         case RENDERPATH_GL11:
6911         case RENDERPATH_GL13:
6912         case RENDERPATH_GLES1:
6913                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6914                 {
6915                         // apply a color tint to the whole view
6916                         R_ResetViewRendering2D(0, NULL, NULL);
6917                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6918                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6919                         R_SetupShader_Generic_NoTexture(false, true);
6920                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6921                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6922                 }
6923                 break;
6924         }
6925 }
6926
6927 matrix4x4_t r_waterscrollmatrix;
6928
6929 void R_UpdateFog(void)
6930 {
6931         // Nehahra fog
6932         if (gamemode == GAME_NEHAHRA)
6933         {
6934                 if (gl_fogenable.integer)
6935                 {
6936                         r_refdef.oldgl_fogenable = true;
6937                         r_refdef.fog_density = gl_fogdensity.value;
6938                         r_refdef.fog_red = gl_fogred.value;
6939                         r_refdef.fog_green = gl_foggreen.value;
6940                         r_refdef.fog_blue = gl_fogblue.value;
6941                         r_refdef.fog_alpha = 1;
6942                         r_refdef.fog_start = 0;
6943                         r_refdef.fog_end = gl_skyclip.value;
6944                         r_refdef.fog_height = 1<<30;
6945                         r_refdef.fog_fadedepth = 128;
6946                 }
6947                 else if (r_refdef.oldgl_fogenable)
6948                 {
6949                         r_refdef.oldgl_fogenable = false;
6950                         r_refdef.fog_density = 0;
6951                         r_refdef.fog_red = 0;
6952                         r_refdef.fog_green = 0;
6953                         r_refdef.fog_blue = 0;
6954                         r_refdef.fog_alpha = 0;
6955                         r_refdef.fog_start = 0;
6956                         r_refdef.fog_end = 0;
6957                         r_refdef.fog_height = 1<<30;
6958                         r_refdef.fog_fadedepth = 128;
6959                 }
6960         }
6961
6962         // fog parms
6963         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6964         r_refdef.fog_start = max(0, r_refdef.fog_start);
6965         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6966
6967         if (r_refdef.fog_density && r_drawfog.integer)
6968         {
6969                 r_refdef.fogenabled = true;
6970                 // this is the point where the fog reaches 0.9986 alpha, which we
6971                 // consider a good enough cutoff point for the texture
6972                 // (0.9986 * 256 == 255.6)
6973                 if (r_fog_exp2.integer)
6974                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6975                 else
6976                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6977                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6978                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6979                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6980                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6981                         R_BuildFogHeightTexture();
6982                 // fog color was already set
6983                 // update the fog texture
6984                 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)
6985                         R_BuildFogTexture();
6986                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6987                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6988         }
6989         else
6990                 r_refdef.fogenabled = false;
6991
6992         // fog color
6993         if (r_refdef.fog_density)
6994         {
6995                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6996                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6997                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6998
6999                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7000                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7001                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7002                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7003
7004                 {
7005                         vec3_t fogvec;
7006                         VectorCopy(r_refdef.fogcolor, fogvec);
7007                         //   color.rgb *= ContrastBoost * SceneBrightness;
7008                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7009                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7010                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7011                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7012                 }
7013         }
7014 }
7015
7016 void R_UpdateVariables(void)
7017 {
7018         R_Textures_Frame();
7019
7020         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7021
7022         r_refdef.farclip = r_farclip_base.value;
7023         if (r_refdef.scene.worldmodel)
7024                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7025         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7026
7027         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7028                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7029         r_refdef.polygonfactor = 0;
7030         r_refdef.polygonoffset = 0;
7031         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7032         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7033
7034         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7035         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7036         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7037         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7038         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7039         if (FAKELIGHT_ENABLED)
7040         {
7041                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7042         }
7043         else if (r_refdef.scene.worldmodel)
7044         {
7045                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7046         }
7047         if (r_showsurfaces.integer)
7048         {
7049                 r_refdef.scene.rtworld = false;
7050                 r_refdef.scene.rtworldshadows = false;
7051                 r_refdef.scene.rtdlight = false;
7052                 r_refdef.scene.rtdlightshadows = false;
7053                 r_refdef.lightmapintensity = 0;
7054         }
7055
7056         r_gpuskeletal = false;
7057         switch(vid.renderpath)
7058         {
7059         case RENDERPATH_GL20:
7060                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7061         case RENDERPATH_D3D9:
7062         case RENDERPATH_D3D10:
7063         case RENDERPATH_D3D11:
7064         case RENDERPATH_SOFT:
7065         case RENDERPATH_GLES2:
7066                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7067                 {
7068                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7069                         {
7070                                 // build GLSL gamma texture
7071 #define RAMPWIDTH 256
7072                                 unsigned short ramp[RAMPWIDTH * 3];
7073                                 unsigned char rampbgr[RAMPWIDTH][4];
7074                                 int i;
7075
7076                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7077
7078                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7079                                 for(i = 0; i < RAMPWIDTH; ++i)
7080                                 {
7081                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7082                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7083                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7084                                         rampbgr[i][3] = 0;
7085                                 }
7086                                 if (r_texture_gammaramps)
7087                                 {
7088                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7089                                 }
7090                                 else
7091                                 {
7092                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7093                                 }
7094                         }
7095                 }
7096                 else
7097                 {
7098                         // remove GLSL gamma texture
7099                 }
7100                 break;
7101         case RENDERPATH_GL11:
7102         case RENDERPATH_GL13:
7103         case RENDERPATH_GLES1:
7104                 break;
7105         }
7106 }
7107
7108 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7109 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7110 /*
7111 ================
7112 R_SelectScene
7113 ================
7114 */
7115 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7116         if( scenetype != r_currentscenetype ) {
7117                 // store the old scenetype
7118                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7119                 r_currentscenetype = scenetype;
7120                 // move in the new scene
7121                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7122         }
7123 }
7124
7125 /*
7126 ================
7127 R_GetScenePointer
7128 ================
7129 */
7130 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7131 {
7132         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7133         if( scenetype == r_currentscenetype ) {
7134                 return &r_refdef.scene;
7135         } else {
7136                 return &r_scenes_store[ scenetype ];
7137         }
7138 }
7139
7140 static int R_SortEntities_Compare(const void *ap, const void *bp)
7141 {
7142         const entity_render_t *a = *(const entity_render_t **)ap;
7143         const entity_render_t *b = *(const entity_render_t **)bp;
7144
7145         // 1. compare model
7146         if(a->model < b->model)
7147                 return -1;
7148         if(a->model > b->model)
7149                 return +1;
7150
7151         // 2. compare skin
7152         // TODO possibly calculate the REAL skinnum here first using
7153         // skinscenes?
7154         if(a->skinnum < b->skinnum)
7155                 return -1;
7156         if(a->skinnum > b->skinnum)
7157                 return +1;
7158
7159         // everything we compared is equal
7160         return 0;
7161 }
7162 static void R_SortEntities(void)
7163 {
7164         // below or equal 2 ents, sorting never gains anything
7165         if(r_refdef.scene.numentities <= 2)
7166                 return;
7167         // sort
7168         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7169 }
7170
7171 /*
7172 ================
7173 R_RenderView
7174 ================
7175 */
7176 int dpsoftrast_test;
7177 extern cvar_t r_shadow_bouncegrid;
7178 void R_RenderView(void)
7179 {
7180         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7181         int fbo;
7182         rtexture_t *depthtexture;
7183         rtexture_t *colortexture;
7184
7185         dpsoftrast_test = r_test.integer;
7186
7187         if (r_timereport_active)
7188                 R_TimeReport("start");
7189         r_textureframe++; // used only by R_GetCurrentTexture
7190         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7191
7192         if(R_CompileShader_CheckStaticParms())
7193                 R_GLSL_Restart_f();
7194
7195         if (!r_drawentities.integer)
7196                 r_refdef.scene.numentities = 0;
7197         else if (r_sortentities.integer)
7198                 R_SortEntities();
7199
7200         R_AnimCache_ClearCache();
7201
7202         /* adjust for stereo display */
7203         if(R_Stereo_Active())
7204         {
7205                 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);
7206                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7207         }
7208
7209         if (r_refdef.view.isoverlay)
7210         {
7211                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7212                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7213                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7214                 R_TimeReport("depthclear");
7215
7216                 r_refdef.view.showdebug = false;
7217
7218                 r_fb.water.enabled = false;
7219                 r_fb.water.numwaterplanes = 0;
7220
7221                 R_RenderScene(0, NULL, NULL);
7222
7223                 r_refdef.view.matrix = originalmatrix;
7224
7225                 CHECKGLERROR
7226                 return;
7227         }
7228
7229         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7230         {
7231                 r_refdef.view.matrix = originalmatrix;
7232                 return;
7233         }
7234
7235         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7236
7237         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7238                 // in sRGB fallback, behave similar to true sRGB: convert this
7239                 // value from linear to sRGB
7240                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7241
7242         R_RenderView_UpdateViewVectors();
7243
7244         R_Shadow_UpdateWorldLightSelection();
7245
7246         R_Bloom_StartFrame();
7247
7248         // apply bloom brightness offset
7249         if(r_fb.bloomtexture[0])
7250                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7251
7252         R_Water_StartFrame();
7253
7254         // now we probably have an fbo to render into
7255         fbo = r_fb.fbo;
7256         depthtexture = r_fb.depthtexture;
7257         colortexture = r_fb.colortexture;
7258
7259         CHECKGLERROR
7260         if (r_timereport_active)
7261                 R_TimeReport("viewsetup");
7262
7263         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7264
7265         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7266         {
7267                 R_ClearScreen(r_refdef.fogenabled);
7268                 if (r_timereport_active)
7269                         R_TimeReport("viewclear");
7270         }
7271         r_refdef.view.clear = true;
7272
7273         r_refdef.view.showdebug = true;
7274
7275         R_View_Update();
7276         if (r_timereport_active)
7277                 R_TimeReport("visibility");
7278
7279         R_AnimCache_CacheVisibleEntities();
7280         if (r_timereport_active)
7281                 R_TimeReport("animcache");
7282
7283         R_Shadow_UpdateBounceGridTexture();
7284         if (r_timereport_active && r_shadow_bouncegrid.integer)
7285                 R_TimeReport("bouncegrid");
7286
7287         r_fb.water.numwaterplanes = 0;
7288         if (r_fb.water.enabled)
7289                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7290
7291         R_RenderScene(fbo, depthtexture, colortexture);
7292         r_fb.water.numwaterplanes = 0;
7293
7294         R_BlendView(fbo, depthtexture, colortexture);
7295         if (r_timereport_active)
7296                 R_TimeReport("blendview");
7297
7298         GL_Scissor(0, 0, vid.width, vid.height);
7299         GL_ScissorTest(false);
7300
7301         r_refdef.view.matrix = originalmatrix;
7302
7303         CHECKGLERROR
7304 }
7305
7306 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7307 {
7308         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7309         {
7310                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7311                 if (r_timereport_active)
7312                         R_TimeReport("waterworld");
7313         }
7314
7315         // don't let sound skip if going slow
7316         if (r_refdef.scene.extraupdate)
7317                 S_ExtraUpdate ();
7318
7319         R_DrawModelsAddWaterPlanes();
7320         if (r_timereport_active)
7321                 R_TimeReport("watermodels");
7322
7323         if (r_fb.water.numwaterplanes)
7324         {
7325                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7326                 if (r_timereport_active)
7327                         R_TimeReport("waterscenes");
7328         }
7329 }
7330
7331 extern cvar_t cl_locs_show;
7332 static void R_DrawLocs(void);
7333 static void R_DrawEntityBBoxes(void);
7334 static void R_DrawModelDecals(void);
7335 extern cvar_t cl_decals_newsystem;
7336 extern qboolean r_shadow_usingdeferredprepass;
7337 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7338 {
7339         qboolean shadowmapping = false;
7340
7341         if (r_timereport_active)
7342                 R_TimeReport("beginscene");
7343
7344         r_refdef.stats[r_stat_renders]++;
7345
7346         R_UpdateFog();
7347
7348         // don't let sound skip if going slow
7349         if (r_refdef.scene.extraupdate)
7350                 S_ExtraUpdate ();
7351
7352         R_MeshQueue_BeginScene();
7353
7354         R_SkyStartFrame();
7355
7356         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);
7357
7358         if (r_timereport_active)
7359                 R_TimeReport("skystartframe");
7360
7361         if (cl.csqc_vidvars.drawworld)
7362         {
7363                 // don't let sound skip if going slow
7364                 if (r_refdef.scene.extraupdate)
7365                         S_ExtraUpdate ();
7366
7367                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7368                 {
7369                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7370                         if (r_timereport_active)
7371                                 R_TimeReport("worldsky");
7372                 }
7373
7374                 if (R_DrawBrushModelsSky() && r_timereport_active)
7375                         R_TimeReport("bmodelsky");
7376
7377                 if (skyrendermasked && skyrenderlater)
7378                 {
7379                         // we have to force off the water clipping plane while rendering sky
7380                         R_SetupView(false, fbo, depthtexture, colortexture);
7381                         R_Sky();
7382                         R_SetupView(true, fbo, depthtexture, colortexture);
7383                         if (r_timereport_active)
7384                                 R_TimeReport("sky");
7385                 }
7386         }
7387
7388         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7389         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7390                 R_Shadow_PrepareModelShadows();
7391         if (r_timereport_active)
7392                 R_TimeReport("preparelights");
7393
7394         if (R_Shadow_ShadowMappingEnabled())
7395                 shadowmapping = true;
7396
7397         if (r_shadow_usingdeferredprepass)
7398                 R_Shadow_DrawPrepass();
7399
7400         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7401         {
7402                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7403                 if (r_timereport_active)
7404                         R_TimeReport("worlddepth");
7405         }
7406         if (r_depthfirst.integer >= 2)
7407         {
7408                 R_DrawModelsDepth();
7409                 if (r_timereport_active)
7410                         R_TimeReport("modeldepth");
7411         }
7412
7413         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7414         {
7415                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7416                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7417                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7418                 // don't let sound skip if going slow
7419                 if (r_refdef.scene.extraupdate)
7420                         S_ExtraUpdate ();
7421         }
7422
7423         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7424         {
7425                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7426                 if (r_timereport_active)
7427                         R_TimeReport("world");
7428         }
7429
7430         // don't let sound skip if going slow
7431         if (r_refdef.scene.extraupdate)
7432                 S_ExtraUpdate ();
7433
7434         R_DrawModels();
7435         if (r_timereport_active)
7436                 R_TimeReport("models");
7437
7438         // don't let sound skip if going slow
7439         if (r_refdef.scene.extraupdate)
7440                 S_ExtraUpdate ();
7441
7442         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7443         {
7444                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7445                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7446                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7447                 // don't let sound skip if going slow
7448                 if (r_refdef.scene.extraupdate)
7449                         S_ExtraUpdate ();
7450         }
7451
7452         if (!r_shadow_usingdeferredprepass)
7453         {
7454                 R_Shadow_DrawLights();
7455                 if (r_timereport_active)
7456                         R_TimeReport("rtlights");
7457         }
7458
7459         // don't let sound skip if going slow
7460         if (r_refdef.scene.extraupdate)
7461                 S_ExtraUpdate ();
7462
7463         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7464         {
7465                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7466                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7467                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7468                 // don't let sound skip if going slow
7469                 if (r_refdef.scene.extraupdate)
7470                         S_ExtraUpdate ();
7471         }
7472
7473         if (cl.csqc_vidvars.drawworld)
7474         {
7475                 if (cl_decals_newsystem.integer)
7476                 {
7477                         R_DrawModelDecals();
7478                         if (r_timereport_active)
7479                                 R_TimeReport("modeldecals");
7480                 }
7481                 else
7482                 {
7483                         R_DrawDecals();
7484                         if (r_timereport_active)
7485                                 R_TimeReport("decals");
7486                 }
7487
7488                 R_DrawParticles();
7489                 if (r_timereport_active)
7490                         R_TimeReport("particles");
7491
7492                 R_DrawExplosions();
7493                 if (r_timereport_active)
7494                         R_TimeReport("explosions");
7495
7496                 R_DrawLightningBeams();
7497                 if (r_timereport_active)
7498                         R_TimeReport("lightning");
7499         }
7500
7501         if (cl.csqc_loaded)
7502                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7503
7504         if (r_refdef.view.showdebug)
7505         {
7506                 if (cl_locs_show.integer)
7507                 {
7508                         R_DrawLocs();
7509                         if (r_timereport_active)
7510                                 R_TimeReport("showlocs");
7511                 }
7512
7513                 if (r_drawportals.integer)
7514                 {
7515                         R_DrawPortals();
7516                         if (r_timereport_active)
7517                                 R_TimeReport("portals");
7518                 }
7519
7520                 if (r_showbboxes.value > 0)
7521                 {
7522                         R_DrawEntityBBoxes();
7523                         if (r_timereport_active)
7524                                 R_TimeReport("bboxes");
7525                 }
7526         }
7527
7528         if (r_transparent.integer)
7529         {
7530                 R_MeshQueue_RenderTransparent();
7531                 if (r_timereport_active)
7532                         R_TimeReport("drawtrans");
7533         }
7534
7535         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))
7536         {
7537                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7538                 if (r_timereport_active)
7539                         R_TimeReport("worlddebug");
7540                 R_DrawModelsDebug();
7541                 if (r_timereport_active)
7542                         R_TimeReport("modeldebug");
7543         }
7544
7545         if (cl.csqc_vidvars.drawworld)
7546         {
7547                 R_Shadow_DrawCoronas();
7548                 if (r_timereport_active)
7549                         R_TimeReport("coronas");
7550         }
7551
7552 #if 0
7553         {
7554                 GL_DepthTest(false);
7555                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7556                 GL_Color(1, 1, 1, 1);
7557                 qglBegin(GL_POLYGON);
7558                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7559                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7560                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7561                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7562                 qglEnd();
7563                 qglBegin(GL_POLYGON);
7564                 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]);
7565                 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]);
7566                 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]);
7567                 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]);
7568                 qglEnd();
7569                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7570         }
7571 #endif
7572
7573         // don't let sound skip if going slow
7574         if (r_refdef.scene.extraupdate)
7575                 S_ExtraUpdate ();
7576 }
7577
7578 static const unsigned short bboxelements[36] =
7579 {
7580         5, 1, 3, 5, 3, 7,
7581         6, 2, 0, 6, 0, 4,
7582         7, 3, 2, 7, 2, 6,
7583         4, 0, 1, 4, 1, 5,
7584         4, 5, 7, 4, 7, 6,
7585         1, 0, 2, 1, 2, 3,
7586 };
7587
7588 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7589 {
7590         int i;
7591         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7592
7593         RSurf_ActiveWorldEntity();
7594
7595         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7596         GL_DepthMask(false);
7597         GL_DepthRange(0, 1);
7598         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7599 //      R_Mesh_ResetTextureState();
7600
7601         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7602         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7603         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7604         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7605         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7606         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7607         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7608         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7609         R_FillColors(color4f, 8, cr, cg, cb, ca);
7610         if (r_refdef.fogenabled)
7611         {
7612                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7613                 {
7614                         f1 = RSurf_FogVertex(v);
7615                         f2 = 1 - f1;
7616                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7617                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7618                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7619                 }
7620         }
7621         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7622         R_Mesh_ResetTextureState();
7623         R_SetupShader_Generic_NoTexture(false, false);
7624         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7625 }
7626
7627 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7628 {
7629         prvm_prog_t *prog = SVVM_prog;
7630         int i;
7631         float color[4];
7632         prvm_edict_t *edict;
7633
7634         // this function draws bounding boxes of server entities
7635         if (!sv.active)
7636                 return;
7637
7638         GL_CullFace(GL_NONE);
7639         R_SetupShader_Generic_NoTexture(false, false);
7640
7641         for (i = 0;i < numsurfaces;i++)
7642         {
7643                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7644                 switch ((int)PRVM_serveredictfloat(edict, solid))
7645                 {
7646                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7647                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7648                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7649                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7650                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7651                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7652                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7653                 }
7654                 color[3] *= r_showbboxes.value;
7655                 color[3] = bound(0, color[3], 1);
7656                 GL_DepthTest(!r_showdisabledepthtest.integer);
7657                 GL_CullFace(r_refdef.view.cullface_front);
7658                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7659         }
7660 }
7661
7662 static void R_DrawEntityBBoxes(void)
7663 {
7664         int i;
7665         prvm_edict_t *edict;
7666         vec3_t center;
7667         prvm_prog_t *prog = SVVM_prog;
7668
7669         // this function draws bounding boxes of server entities
7670         if (!sv.active)
7671                 return;
7672
7673         for (i = 0;i < prog->num_edicts;i++)
7674         {
7675                 edict = PRVM_EDICT_NUM(i);
7676                 if (edict->priv.server->free)
7677                         continue;
7678                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7679                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7680                         continue;
7681                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7682                         continue;
7683                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7684                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7685         }
7686 }
7687
7688 static const int nomodelelement3i[24] =
7689 {
7690         5, 2, 0,
7691         5, 1, 2,
7692         5, 0, 3,
7693         5, 3, 1,
7694         0, 2, 4,
7695         2, 1, 4,
7696         3, 0, 4,
7697         1, 3, 4
7698 };
7699
7700 static const unsigned short nomodelelement3s[24] =
7701 {
7702         5, 2, 0,
7703         5, 1, 2,
7704         5, 0, 3,
7705         5, 3, 1,
7706         0, 2, 4,
7707         2, 1, 4,
7708         3, 0, 4,
7709         1, 3, 4
7710 };
7711
7712 static const float nomodelvertex3f[6*3] =
7713 {
7714         -16,   0,   0,
7715          16,   0,   0,
7716           0, -16,   0,
7717           0,  16,   0,
7718           0,   0, -16,
7719           0,   0,  16
7720 };
7721
7722 static const float nomodelcolor4f[6*4] =
7723 {
7724         0.0f, 0.0f, 0.5f, 1.0f,
7725         0.0f, 0.0f, 0.5f, 1.0f,
7726         0.0f, 0.5f, 0.0f, 1.0f,
7727         0.0f, 0.5f, 0.0f, 1.0f,
7728         0.5f, 0.0f, 0.0f, 1.0f,
7729         0.5f, 0.0f, 0.0f, 1.0f
7730 };
7731
7732 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7733 {
7734         int i;
7735         float f1, f2, *c;
7736         float color4f[6*4];
7737
7738         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);
7739
7740         // this is only called once per entity so numsurfaces is always 1, and
7741         // surfacelist is always {0}, so this code does not handle batches
7742
7743         if (rsurface.ent_flags & RENDER_ADDITIVE)
7744         {
7745                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7746                 GL_DepthMask(false);
7747         }
7748         else if (rsurface.colormod[3] < 1)
7749         {
7750                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7751                 GL_DepthMask(false);
7752         }
7753         else
7754         {
7755                 GL_BlendFunc(GL_ONE, GL_ZERO);
7756                 GL_DepthMask(true);
7757         }
7758         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7759         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7760         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7761         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7762         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7763         for (i = 0, c = color4f;i < 6;i++, c += 4)
7764         {
7765                 c[0] *= rsurface.colormod[0];
7766                 c[1] *= rsurface.colormod[1];
7767                 c[2] *= rsurface.colormod[2];
7768                 c[3] *= rsurface.colormod[3];
7769         }
7770         if (r_refdef.fogenabled)
7771         {
7772                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7773                 {
7774                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7775                         f2 = 1 - f1;
7776                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7777                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7778                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7779                 }
7780         }
7781 //      R_Mesh_ResetTextureState();
7782         R_SetupShader_Generic_NoTexture(false, false);
7783         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7784         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7785 }
7786
7787 void R_DrawNoModel(entity_render_t *ent)
7788 {
7789         vec3_t org;
7790         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7791         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7792                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7793         else
7794                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7795 }
7796
7797 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7798 {
7799         vec3_t right1, right2, diff, normal;
7800
7801         VectorSubtract (org2, org1, normal);
7802
7803         // calculate 'right' vector for start
7804         VectorSubtract (r_refdef.view.origin, org1, diff);
7805         CrossProduct (normal, diff, right1);
7806         VectorNormalize (right1);
7807
7808         // calculate 'right' vector for end
7809         VectorSubtract (r_refdef.view.origin, org2, diff);
7810         CrossProduct (normal, diff, right2);
7811         VectorNormalize (right2);
7812
7813         vert[ 0] = org1[0] + width * right1[0];
7814         vert[ 1] = org1[1] + width * right1[1];
7815         vert[ 2] = org1[2] + width * right1[2];
7816         vert[ 3] = org1[0] - width * right1[0];
7817         vert[ 4] = org1[1] - width * right1[1];
7818         vert[ 5] = org1[2] - width * right1[2];
7819         vert[ 6] = org2[0] - width * right2[0];
7820         vert[ 7] = org2[1] - width * right2[1];
7821         vert[ 8] = org2[2] - width * right2[2];
7822         vert[ 9] = org2[0] + width * right2[0];
7823         vert[10] = org2[1] + width * right2[1];
7824         vert[11] = org2[2] + width * right2[2];
7825 }
7826
7827 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)
7828 {
7829         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7830         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7831         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7832         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7833         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7834         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7835         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7836         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7837         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7838         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7839         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7840         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7841 }
7842
7843 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7844 {
7845         int i;
7846         float *vertex3f;
7847         float v[3];
7848         VectorSet(v, x, y, z);
7849         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7850                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7851                         break;
7852         if (i == mesh->numvertices)
7853         {
7854                 if (mesh->numvertices < mesh->maxvertices)
7855                 {
7856                         VectorCopy(v, vertex3f);
7857                         mesh->numvertices++;
7858                 }
7859                 return mesh->numvertices;
7860         }
7861         else
7862                 return i;
7863 }
7864
7865 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7866 {
7867         int i;
7868         int *e, element[3];
7869         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7870         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7871         e = mesh->element3i + mesh->numtriangles * 3;
7872         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7873         {
7874                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7875                 if (mesh->numtriangles < mesh->maxtriangles)
7876                 {
7877                         *e++ = element[0];
7878                         *e++ = element[1];
7879                         *e++ = element[2];
7880                         mesh->numtriangles++;
7881                 }
7882                 element[1] = element[2];
7883         }
7884 }
7885
7886 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7887 {
7888         int i;
7889         int *e, element[3];
7890         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7891         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7892         e = mesh->element3i + mesh->numtriangles * 3;
7893         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7894         {
7895                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7896                 if (mesh->numtriangles < mesh->maxtriangles)
7897                 {
7898                         *e++ = element[0];
7899                         *e++ = element[1];
7900                         *e++ = element[2];
7901                         mesh->numtriangles++;
7902                 }
7903                 element[1] = element[2];
7904         }
7905 }
7906
7907 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7908 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7909 {
7910         int planenum, planenum2;
7911         int w;
7912         int tempnumpoints;
7913         mplane_t *plane, *plane2;
7914         double maxdist;
7915         double temppoints[2][256*3];
7916         // figure out how large a bounding box we need to properly compute this brush
7917         maxdist = 0;
7918         for (w = 0;w < numplanes;w++)
7919                 maxdist = max(maxdist, fabs(planes[w].dist));
7920         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7921         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7922         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7923         {
7924                 w = 0;
7925                 tempnumpoints = 4;
7926                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7927                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7928                 {
7929                         if (planenum2 == planenum)
7930                                 continue;
7931                         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);
7932                         w = !w;
7933                 }
7934                 if (tempnumpoints < 3)
7935                         continue;
7936                 // generate elements forming a triangle fan for this polygon
7937                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7938         }
7939 }
7940
7941 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)
7942 {
7943         texturelayer_t *layer;
7944         layer = t->currentlayers + t->currentnumlayers++;
7945         layer->type = type;
7946         layer->depthmask = depthmask;
7947         layer->blendfunc1 = blendfunc1;
7948         layer->blendfunc2 = blendfunc2;
7949         layer->texture = texture;
7950         layer->texmatrix = *matrix;
7951         layer->color[0] = r;
7952         layer->color[1] = g;
7953         layer->color[2] = b;
7954         layer->color[3] = a;
7955 }
7956
7957 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7958 {
7959         if(parms[0] == 0 && parms[1] == 0)
7960                 return false;
7961         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7962                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7963                         return false;
7964         return true;
7965 }
7966
7967 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7968 {
7969         double index, f;
7970         index = parms[2] + rsurface.shadertime * parms[3];
7971         index -= floor(index);
7972         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7973         {
7974         default:
7975         case Q3WAVEFUNC_NONE:
7976         case Q3WAVEFUNC_NOISE:
7977         case Q3WAVEFUNC_COUNT:
7978                 f = 0;
7979                 break;
7980         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7981         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7982         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7983         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7984         case Q3WAVEFUNC_TRIANGLE:
7985                 index *= 4;
7986                 f = index - floor(index);
7987                 if (index < 1)
7988                 {
7989                         // f = f;
7990                 }
7991                 else if (index < 2)
7992                         f = 1 - f;
7993                 else if (index < 3)
7994                         f = -f;
7995                 else
7996                         f = -(1 - f);
7997                 break;
7998         }
7999         f = parms[0] + parms[1] * f;
8000         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8001                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8002         return (float) f;
8003 }
8004
8005 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8006 {
8007         int w, h, idx;
8008         float shadertime;
8009         float f;
8010         float offsetd[2];
8011         float tcmat[12];
8012         matrix4x4_t matrix, temp;
8013         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8014         // it's better to have one huge fixup every 9 hours than gradual
8015         // degradation over time which looks consistently bad after many hours.
8016         //
8017         // tcmod scroll in particular suffers from this degradation which can't be
8018         // effectively worked around even with floor() tricks because we don't
8019         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8020         // a workaround involving floor() would be incorrect anyway...
8021         shadertime = rsurface.shadertime;
8022         if (shadertime >= 32768.0f)
8023                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8024         switch(tcmod->tcmod)
8025         {
8026                 case Q3TCMOD_COUNT:
8027                 case Q3TCMOD_NONE:
8028                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8029                                 matrix = r_waterscrollmatrix;
8030                         else
8031                                 matrix = identitymatrix;
8032                         break;
8033                 case Q3TCMOD_ENTITYTRANSLATE:
8034                         // this is used in Q3 to allow the gamecode to control texcoord
8035                         // scrolling on the entity, which is not supported in darkplaces yet.
8036                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8037                         break;
8038                 case Q3TCMOD_ROTATE:
8039                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8040                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8041                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8042                         break;
8043                 case Q3TCMOD_SCALE:
8044                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8045                         break;
8046                 case Q3TCMOD_SCROLL:
8047                         // this particular tcmod is a "bug for bug" compatible one with regards to
8048                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8049                         // specifically did the wrapping and so we must mimic that...
8050                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8051                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8052                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8053                         break;
8054                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8055                         w = (int) tcmod->parms[0];
8056                         h = (int) tcmod->parms[1];
8057                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8058                         f = f - floor(f);
8059                         idx = (int) floor(f * w * h);
8060                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8061                         break;
8062                 case Q3TCMOD_STRETCH:
8063                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8064                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8065                         break;
8066                 case Q3TCMOD_TRANSFORM:
8067                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8068                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8069                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8070                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8071                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8072                         break;
8073                 case Q3TCMOD_TURBULENT:
8074                         // this is handled in the RSurf_PrepareVertices function
8075                         matrix = identitymatrix;
8076                         break;
8077         }
8078         temp = *texmatrix;
8079         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8080 }
8081
8082 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8083 {
8084         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8085         char name[MAX_QPATH];
8086         skinframe_t *skinframe;
8087         unsigned char pixels[296*194];
8088         strlcpy(cache->name, skinname, sizeof(cache->name));
8089         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8090         if (developer_loading.integer)
8091                 Con_Printf("loading %s\n", name);
8092         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8093         if (!skinframe || !skinframe->base)
8094         {
8095                 unsigned char *f;
8096                 fs_offset_t filesize;
8097                 skinframe = NULL;
8098                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8099                 if (f)
8100                 {
8101                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8102                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8103                         Mem_Free(f);
8104                 }
8105         }
8106         cache->skinframe = skinframe;
8107 }
8108
8109 texture_t *R_GetCurrentTexture(texture_t *t)
8110 {
8111         int i;
8112         const entity_render_t *ent = rsurface.entity;
8113         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8114         q3shaderinfo_layer_tcmod_t *tcmod;
8115
8116         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8117                 return t->currentframe;
8118         t->update_lastrenderframe = r_textureframe;
8119         t->update_lastrenderentity = (void *)ent;
8120
8121         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8122                 t->camera_entity = ent->entitynumber;
8123         else
8124                 t->camera_entity = 0;
8125
8126         // switch to an alternate material if this is a q1bsp animated material
8127         {
8128                 texture_t *texture = t;
8129                 int s = rsurface.ent_skinnum;
8130                 if ((unsigned int)s >= (unsigned int)model->numskins)
8131                         s = 0;
8132                 if (model->skinscenes)
8133                 {
8134                         if (model->skinscenes[s].framecount > 1)
8135                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8136                         else
8137                                 s = model->skinscenes[s].firstframe;
8138                 }
8139                 if (s > 0)
8140                         t = t + s * model->num_surfaces;
8141                 if (t->animated)
8142                 {
8143                         // use an alternate animation if the entity's frame is not 0,
8144                         // and only if the texture has an alternate animation
8145                         if (rsurface.ent_alttextures && t->anim_total[1])
8146                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8147                         else
8148                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8149                 }
8150                 texture->currentframe = t;
8151         }
8152
8153         // update currentskinframe to be a qw skin or animation frame
8154         if (rsurface.ent_qwskin >= 0)
8155         {
8156                 i = rsurface.ent_qwskin;
8157                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8158                 {
8159                         r_qwskincache_size = cl.maxclients;
8160                         if (r_qwskincache)
8161                                 Mem_Free(r_qwskincache);
8162                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8163                 }
8164                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8165                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8166                 t->currentskinframe = r_qwskincache[i].skinframe;
8167                 if (t->currentskinframe == NULL)
8168                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8169         }
8170         else if (t->numskinframes >= 2)
8171                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8172         if (t->backgroundnumskinframes >= 2)
8173                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8174
8175         t->currentmaterialflags = t->basematerialflags;
8176         t->currentalpha = rsurface.colormod[3];
8177         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8178                 t->currentalpha *= r_wateralpha.value;
8179         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8180                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8181         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8182                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8183         if (!(rsurface.ent_flags & RENDER_LIGHT))
8184                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8185         else if (FAKELIGHT_ENABLED)
8186         {
8187                 // no modellight if using fakelight for the map
8188         }
8189         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8190         {
8191                 // pick a model lighting mode
8192                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8193                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8194                 else
8195                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8196         }
8197         if (rsurface.ent_flags & RENDER_ADDITIVE)
8198                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8199         else if (t->currentalpha < 1)
8200                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8201         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8202         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8203                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8204         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8205                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8206         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8207                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8208         if (t->backgroundnumskinframes)
8209                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8210         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8211         {
8212                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8213                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8214         }
8215         else
8216                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8217         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8218         {
8219                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8220                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8221         }
8222         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8223                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8224
8225         // there is no tcmod
8226         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8227         {
8228                 t->currenttexmatrix = r_waterscrollmatrix;
8229                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8230         }
8231         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8232         {
8233                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8234                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8235         }
8236
8237         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8238                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8239         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8240                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8241
8242         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8243         if (t->currentskinframe->qpixels)
8244                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8245         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8246         if (!t->basetexture)
8247                 t->basetexture = r_texture_notexture;
8248         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8249         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8250         t->nmaptexture = t->currentskinframe->nmap;
8251         if (!t->nmaptexture)
8252                 t->nmaptexture = r_texture_blanknormalmap;
8253         t->glosstexture = r_texture_black;
8254         t->glowtexture = t->currentskinframe->glow;
8255         t->fogtexture = t->currentskinframe->fog;
8256         t->reflectmasktexture = t->currentskinframe->reflect;
8257         if (t->backgroundnumskinframes)
8258         {
8259                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8260                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8261                 t->backgroundglosstexture = r_texture_black;
8262                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8263                 if (!t->backgroundnmaptexture)
8264                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8265                 // make sure that if glow is going to be used, both textures are not NULL
8266                 if (!t->backgroundglowtexture && t->glowtexture)
8267                         t->backgroundglowtexture = r_texture_black;
8268                 if (!t->glowtexture && t->backgroundglowtexture)
8269                         t->glowtexture = r_texture_black;
8270         }
8271         else
8272         {
8273                 t->backgroundbasetexture = r_texture_white;
8274                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8275                 t->backgroundglosstexture = r_texture_black;
8276                 t->backgroundglowtexture = NULL;
8277         }
8278         t->specularpower = r_shadow_glossexponent.value;
8279         // TODO: store reference values for these in the texture?
8280         t->specularscale = 0;
8281         if (r_shadow_gloss.integer > 0)
8282         {
8283                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8284                 {
8285                         if (r_shadow_glossintensity.value > 0)
8286                         {
8287                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8288                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8289                                 t->specularscale = r_shadow_glossintensity.value;
8290                         }
8291                 }
8292                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8293                 {
8294                         t->glosstexture = r_texture_white;
8295                         t->backgroundglosstexture = r_texture_white;
8296                         t->specularscale = r_shadow_gloss2intensity.value;
8297                         t->specularpower = r_shadow_gloss2exponent.value;
8298                 }
8299         }
8300         t->specularscale *= t->specularscalemod;
8301         t->specularpower *= t->specularpowermod;
8302         t->rtlightambient = 0;
8303
8304         // lightmaps mode looks bad with dlights using actual texturing, so turn
8305         // off the colormap and glossmap, but leave the normalmap on as it still
8306         // accurately represents the shading involved
8307         if (gl_lightmaps.integer)
8308         {
8309                 t->basetexture = r_texture_grey128;
8310                 t->pantstexture = r_texture_black;
8311                 t->shirttexture = r_texture_black;
8312                 if (gl_lightmaps.integer < 2)
8313                         t->nmaptexture = r_texture_blanknormalmap;
8314                 t->glosstexture = r_texture_black;
8315                 t->glowtexture = NULL;
8316                 t->fogtexture = NULL;
8317                 t->reflectmasktexture = NULL;
8318                 t->backgroundbasetexture = NULL;
8319                 if (gl_lightmaps.integer < 2)
8320                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8321                 t->backgroundglosstexture = r_texture_black;
8322                 t->backgroundglowtexture = NULL;
8323                 t->specularscale = 0;
8324                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8325         }
8326
8327         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8328         VectorClear(t->dlightcolor);
8329         t->currentnumlayers = 0;
8330         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8331         {
8332                 int blendfunc1, blendfunc2;
8333                 qboolean depthmask;
8334                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8335                 {
8336                         blendfunc1 = GL_SRC_ALPHA;
8337                         blendfunc2 = GL_ONE;
8338                 }
8339                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8340                 {
8341                         blendfunc1 = GL_SRC_ALPHA;
8342                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8343                 }
8344                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8345                 {
8346                         blendfunc1 = t->customblendfunc[0];
8347                         blendfunc2 = t->customblendfunc[1];
8348                 }
8349                 else
8350                 {
8351                         blendfunc1 = GL_ONE;
8352                         blendfunc2 = GL_ZERO;
8353                 }
8354                 // don't colormod evilblend textures
8355                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8356                         VectorSet(t->lightmapcolor, 1, 1, 1);
8357                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8358                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8359                 {
8360                         // fullbright is not affected by r_refdef.lightmapintensity
8361                         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]);
8362                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8363                                 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]);
8364                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8365                                 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]);
8366                 }
8367                 else
8368                 {
8369                         vec3_t ambientcolor;
8370                         float colorscale;
8371                         // set the color tint used for lights affecting this surface
8372                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8373                         colorscale = 2;
8374                         // q3bsp has no lightmap updates, so the lightstylevalue that
8375                         // would normally be baked into the lightmap must be
8376                         // applied to the color
8377                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8378                         if (model->type == mod_brushq3)
8379                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8380                         colorscale *= r_refdef.lightmapintensity;
8381                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8382                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8383                         // basic lit geometry
8384                         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]);
8385                         // add pants/shirt if needed
8386                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8387                                 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]);
8388                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8389                                 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]);
8390                         // now add ambient passes if needed
8391                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8392                         {
8393                                 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]);
8394                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8395                                         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]);
8396                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8397                                         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]);
8398                         }
8399                 }
8400                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8401                         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]);
8402                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8403                 {
8404                         // if this is opaque use alpha blend which will darken the earlier
8405                         // passes cheaply.
8406                         //
8407                         // if this is an alpha blended material, all the earlier passes
8408                         // were darkened by fog already, so we only need to add the fog
8409                         // color ontop through the fog mask texture
8410                         //
8411                         // if this is an additive blended material, all the earlier passes
8412                         // were darkened by fog already, and we should not add fog color
8413                         // (because the background was not darkened, there is no fog color
8414                         // that was lost behind it).
8415                         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]);
8416                 }
8417         }
8418
8419         return t->currentframe;
8420 }
8421
8422 rsurfacestate_t rsurface;
8423
8424 void RSurf_ActiveWorldEntity(void)
8425 {
8426         dp_model_t *model = r_refdef.scene.worldmodel;
8427         //if (rsurface.entity == r_refdef.scene.worldentity)
8428         //      return;
8429         rsurface.entity = r_refdef.scene.worldentity;
8430         rsurface.skeleton = NULL;
8431         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8432         rsurface.ent_skinnum = 0;
8433         rsurface.ent_qwskin = -1;
8434         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8435         rsurface.shadertime = r_refdef.scene.time;
8436         rsurface.matrix = identitymatrix;
8437         rsurface.inversematrix = identitymatrix;
8438         rsurface.matrixscale = 1;
8439         rsurface.inversematrixscale = 1;
8440         R_EntityMatrix(&identitymatrix);
8441         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8442         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8443         rsurface.fograngerecip = r_refdef.fograngerecip;
8444         rsurface.fogheightfade = r_refdef.fogheightfade;
8445         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8446         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8447         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8448         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8449         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8450         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8451         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8452         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8453         rsurface.colormod[3] = 1;
8454         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);
8455         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8456         rsurface.frameblend[0].lerp = 1;
8457         rsurface.ent_alttextures = false;
8458         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8459         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8460         rsurface.entityskeletaltransform3x4 = NULL;
8461         rsurface.entityskeletaltransform3x4buffer = NULL;
8462         rsurface.entityskeletaltransform3x4offset = 0;
8463         rsurface.entityskeletaltransform3x4size = 0;;
8464         rsurface.entityskeletalnumtransforms = 0;
8465         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8466         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8467         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8468         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8469         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8470         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8471         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8472         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8473         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8474         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8475         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8476         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8477         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8478         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8479         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8480         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8481         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8482         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8483         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8484         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8485         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8486         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8487         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8488         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8489         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8490         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8491         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8492         rsurface.modelelement3i = model->surfmesh.data_element3i;
8493         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8494         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8495         rsurface.modelelement3s = model->surfmesh.data_element3s;
8496         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8497         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8498         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8499         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8500         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8501         rsurface.modelsurfaces = model->data_surfaces;
8502         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8503         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8504         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8505         rsurface.modelgeneratedvertex = false;
8506         rsurface.batchgeneratedvertex = false;
8507         rsurface.batchfirstvertex = 0;
8508         rsurface.batchnumvertices = 0;
8509         rsurface.batchfirsttriangle = 0;
8510         rsurface.batchnumtriangles = 0;
8511         rsurface.batchvertex3f  = NULL;
8512         rsurface.batchvertex3f_vertexbuffer = NULL;
8513         rsurface.batchvertex3f_bufferoffset = 0;
8514         rsurface.batchsvector3f = NULL;
8515         rsurface.batchsvector3f_vertexbuffer = NULL;
8516         rsurface.batchsvector3f_bufferoffset = 0;
8517         rsurface.batchtvector3f = NULL;
8518         rsurface.batchtvector3f_vertexbuffer = NULL;
8519         rsurface.batchtvector3f_bufferoffset = 0;
8520         rsurface.batchnormal3f  = NULL;
8521         rsurface.batchnormal3f_vertexbuffer = NULL;
8522         rsurface.batchnormal3f_bufferoffset = 0;
8523         rsurface.batchlightmapcolor4f = NULL;
8524         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8525         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8526         rsurface.batchtexcoordtexture2f = NULL;
8527         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8528         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8529         rsurface.batchtexcoordlightmap2f = NULL;
8530         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8531         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8532         rsurface.batchskeletalindex4ub = NULL;
8533         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8534         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8535         rsurface.batchskeletalweight4ub = NULL;
8536         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8537         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8538         rsurface.batchvertexmesh = NULL;
8539         rsurface.batchvertexmesh_vertexbuffer = NULL;
8540         rsurface.batchvertexmesh_bufferoffset = 0;
8541         rsurface.batchelement3i = NULL;
8542         rsurface.batchelement3i_indexbuffer = NULL;
8543         rsurface.batchelement3i_bufferoffset = 0;
8544         rsurface.batchelement3s = NULL;
8545         rsurface.batchelement3s_indexbuffer = NULL;
8546         rsurface.batchelement3s_bufferoffset = 0;
8547         rsurface.passcolor4f = NULL;
8548         rsurface.passcolor4f_vertexbuffer = NULL;
8549         rsurface.passcolor4f_bufferoffset = 0;
8550         rsurface.forcecurrenttextureupdate = false;
8551 }
8552
8553 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8554 {
8555         dp_model_t *model = ent->model;
8556         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8557         //      return;
8558         rsurface.entity = (entity_render_t *)ent;
8559         rsurface.skeleton = ent->skeleton;
8560         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8561         rsurface.ent_skinnum = ent->skinnum;
8562         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;
8563         rsurface.ent_flags = ent->flags;
8564         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8565         rsurface.matrix = ent->matrix;
8566         rsurface.inversematrix = ent->inversematrix;
8567         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8568         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8569         R_EntityMatrix(&rsurface.matrix);
8570         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8571         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8572         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8573         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8574         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8575         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8576         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8577         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8578         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8579         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8580         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8581         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8582         rsurface.colormod[3] = ent->alpha;
8583         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8584         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8585         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8586         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8587         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8588         if (ent->model->brush.submodel && !prepass)
8589         {
8590                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8591                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8592         }
8593         // if the animcache code decided it should use the shader path, skip the deform step
8594         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8595         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8596         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8597         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8598         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8599         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8600         {
8601                 if (ent->animcache_vertex3f)
8602                 {
8603                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8604                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8605                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8606                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8607                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8608                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8609                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8610                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8611                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8612                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8613                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8614                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8615                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8616                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8617                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8618                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8619                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8620                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8621                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8622                 }
8623                 else if (wanttangents)
8624                 {
8625                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8626                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8627                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8628                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8629                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8630                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8631                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8632                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8633                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8634                         rsurface.modelvertexmesh = NULL;
8635                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8636                         rsurface.modelvertexmesh_bufferoffset = 0;
8637                         rsurface.modelvertex3f_vertexbuffer = NULL;
8638                         rsurface.modelvertex3f_bufferoffset = 0;
8639                         rsurface.modelvertex3f_vertexbuffer = 0;
8640                         rsurface.modelvertex3f_bufferoffset = 0;
8641                         rsurface.modelsvector3f_vertexbuffer = 0;
8642                         rsurface.modelsvector3f_bufferoffset = 0;
8643                         rsurface.modeltvector3f_vertexbuffer = 0;
8644                         rsurface.modeltvector3f_bufferoffset = 0;
8645                         rsurface.modelnormal3f_vertexbuffer = 0;
8646                         rsurface.modelnormal3f_bufferoffset = 0;
8647                 }
8648                 else if (wantnormals)
8649                 {
8650                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8651                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8652                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8653                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8654                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8655                         rsurface.modelsvector3f = NULL;
8656                         rsurface.modeltvector3f = NULL;
8657                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8658                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8659                         rsurface.modelvertexmesh = NULL;
8660                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8661                         rsurface.modelvertexmesh_bufferoffset = 0;
8662                         rsurface.modelvertex3f_vertexbuffer = NULL;
8663                         rsurface.modelvertex3f_bufferoffset = 0;
8664                         rsurface.modelvertex3f_vertexbuffer = 0;
8665                         rsurface.modelvertex3f_bufferoffset = 0;
8666                         rsurface.modelsvector3f_vertexbuffer = 0;
8667                         rsurface.modelsvector3f_bufferoffset = 0;
8668                         rsurface.modeltvector3f_vertexbuffer = 0;
8669                         rsurface.modeltvector3f_bufferoffset = 0;
8670                         rsurface.modelnormal3f_vertexbuffer = 0;
8671                         rsurface.modelnormal3f_bufferoffset = 0;
8672                 }
8673                 else
8674                 {
8675                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8676                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8677                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8678                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8679                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8680                         rsurface.modelsvector3f = NULL;
8681                         rsurface.modeltvector3f = NULL;
8682                         rsurface.modelnormal3f = NULL;
8683                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8684                         rsurface.modelvertexmesh = NULL;
8685                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8686                         rsurface.modelvertexmesh_bufferoffset = 0;
8687                         rsurface.modelvertex3f_vertexbuffer = NULL;
8688                         rsurface.modelvertex3f_bufferoffset = 0;
8689                         rsurface.modelvertex3f_vertexbuffer = 0;
8690                         rsurface.modelvertex3f_bufferoffset = 0;
8691                         rsurface.modelsvector3f_vertexbuffer = 0;
8692                         rsurface.modelsvector3f_bufferoffset = 0;
8693                         rsurface.modeltvector3f_vertexbuffer = 0;
8694                         rsurface.modeltvector3f_bufferoffset = 0;
8695                         rsurface.modelnormal3f_vertexbuffer = 0;
8696                         rsurface.modelnormal3f_bufferoffset = 0;
8697                 }
8698                 rsurface.modelgeneratedvertex = true;
8699         }
8700         else
8701         {
8702                 if (rsurface.entityskeletaltransform3x4)
8703                 {
8704                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8705                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8706                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8707                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8708                 }
8709                 else
8710                 {
8711                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8712                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8713                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8714                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8715                 }
8716                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8717                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8718                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8719                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8720                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8721                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8722                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8723                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8724                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8725                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8726                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8727                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8728                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8729                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8730                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8731                 rsurface.modelgeneratedvertex = false;
8732         }
8733         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8734         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8735         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8736         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8737         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8738         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8739         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8740         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8741         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8742         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8743         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8744         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8745         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8746         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8747         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8748         rsurface.modelelement3i = model->surfmesh.data_element3i;
8749         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8750         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8751         rsurface.modelelement3s = model->surfmesh.data_element3s;
8752         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8753         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8754         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8755         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8756         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8757         rsurface.modelsurfaces = model->data_surfaces;
8758         rsurface.batchgeneratedvertex = false;
8759         rsurface.batchfirstvertex = 0;
8760         rsurface.batchnumvertices = 0;
8761         rsurface.batchfirsttriangle = 0;
8762         rsurface.batchnumtriangles = 0;
8763         rsurface.batchvertex3f  = NULL;
8764         rsurface.batchvertex3f_vertexbuffer = NULL;
8765         rsurface.batchvertex3f_bufferoffset = 0;
8766         rsurface.batchsvector3f = NULL;
8767         rsurface.batchsvector3f_vertexbuffer = NULL;
8768         rsurface.batchsvector3f_bufferoffset = 0;
8769         rsurface.batchtvector3f = NULL;
8770         rsurface.batchtvector3f_vertexbuffer = NULL;
8771         rsurface.batchtvector3f_bufferoffset = 0;
8772         rsurface.batchnormal3f  = NULL;
8773         rsurface.batchnormal3f_vertexbuffer = NULL;
8774         rsurface.batchnormal3f_bufferoffset = 0;
8775         rsurface.batchlightmapcolor4f = NULL;
8776         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8777         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8778         rsurface.batchtexcoordtexture2f = NULL;
8779         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8780         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8781         rsurface.batchtexcoordlightmap2f = NULL;
8782         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8783         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8784         rsurface.batchskeletalindex4ub = NULL;
8785         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8786         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8787         rsurface.batchskeletalweight4ub = NULL;
8788         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8789         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8790         rsurface.batchvertexmesh = NULL;
8791         rsurface.batchvertexmesh_vertexbuffer = NULL;
8792         rsurface.batchvertexmesh_bufferoffset = 0;
8793         rsurface.batchelement3i = NULL;
8794         rsurface.batchelement3i_indexbuffer = NULL;
8795         rsurface.batchelement3i_bufferoffset = 0;
8796         rsurface.batchelement3s = NULL;
8797         rsurface.batchelement3s_indexbuffer = NULL;
8798         rsurface.batchelement3s_bufferoffset = 0;
8799         rsurface.passcolor4f = NULL;
8800         rsurface.passcolor4f_vertexbuffer = NULL;
8801         rsurface.passcolor4f_bufferoffset = 0;
8802         rsurface.forcecurrenttextureupdate = false;
8803 }
8804
8805 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)
8806 {
8807         rsurface.entity = r_refdef.scene.worldentity;
8808         rsurface.skeleton = NULL;
8809         rsurface.ent_skinnum = 0;
8810         rsurface.ent_qwskin = -1;
8811         rsurface.ent_flags = entflags;
8812         rsurface.shadertime = r_refdef.scene.time - shadertime;
8813         rsurface.modelnumvertices = numvertices;
8814         rsurface.modelnumtriangles = numtriangles;
8815         rsurface.matrix = *matrix;
8816         rsurface.inversematrix = *inversematrix;
8817         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8818         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8819         R_EntityMatrix(&rsurface.matrix);
8820         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8821         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8822         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8823         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8824         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8825         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8826         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8827         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8828         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8829         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8830         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8831         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8832         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);
8833         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8834         rsurface.frameblend[0].lerp = 1;
8835         rsurface.ent_alttextures = false;
8836         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8837         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8838         rsurface.entityskeletaltransform3x4 = NULL;
8839         rsurface.entityskeletaltransform3x4buffer = NULL;
8840         rsurface.entityskeletaltransform3x4offset = 0;
8841         rsurface.entityskeletaltransform3x4size = 0;
8842         rsurface.entityskeletalnumtransforms = 0;
8843         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8844         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8845         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8846         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8847         if (wanttangents)
8848         {
8849                 rsurface.modelvertex3f = (float *)vertex3f;
8850                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8851                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8852                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8853         }
8854         else if (wantnormals)
8855         {
8856                 rsurface.modelvertex3f = (float *)vertex3f;
8857                 rsurface.modelsvector3f = NULL;
8858                 rsurface.modeltvector3f = NULL;
8859                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8860         }
8861         else
8862         {
8863                 rsurface.modelvertex3f = (float *)vertex3f;
8864                 rsurface.modelsvector3f = NULL;
8865                 rsurface.modeltvector3f = NULL;
8866                 rsurface.modelnormal3f = NULL;
8867         }
8868         rsurface.modelvertexmesh = NULL;
8869         rsurface.modelvertexmesh_vertexbuffer = NULL;
8870         rsurface.modelvertexmesh_bufferoffset = 0;
8871         rsurface.modelvertex3f_vertexbuffer = 0;
8872         rsurface.modelvertex3f_bufferoffset = 0;
8873         rsurface.modelsvector3f_vertexbuffer = 0;
8874         rsurface.modelsvector3f_bufferoffset = 0;
8875         rsurface.modeltvector3f_vertexbuffer = 0;
8876         rsurface.modeltvector3f_bufferoffset = 0;
8877         rsurface.modelnormal3f_vertexbuffer = 0;
8878         rsurface.modelnormal3f_bufferoffset = 0;
8879         rsurface.modelgeneratedvertex = true;
8880         rsurface.modellightmapcolor4f  = (float *)color4f;
8881         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8882         rsurface.modellightmapcolor4f_bufferoffset = 0;
8883         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8884         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8885         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8886         rsurface.modeltexcoordlightmap2f  = NULL;
8887         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8888         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8889         rsurface.modelskeletalindex4ub = NULL;
8890         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8891         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8892         rsurface.modelskeletalweight4ub = NULL;
8893         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8894         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8895         rsurface.modelelement3i = (int *)element3i;
8896         rsurface.modelelement3i_indexbuffer = NULL;
8897         rsurface.modelelement3i_bufferoffset = 0;
8898         rsurface.modelelement3s = (unsigned short *)element3s;
8899         rsurface.modelelement3s_indexbuffer = NULL;
8900         rsurface.modelelement3s_bufferoffset = 0;
8901         rsurface.modellightmapoffsets = NULL;
8902         rsurface.modelsurfaces = NULL;
8903         rsurface.batchgeneratedvertex = false;
8904         rsurface.batchfirstvertex = 0;
8905         rsurface.batchnumvertices = 0;
8906         rsurface.batchfirsttriangle = 0;
8907         rsurface.batchnumtriangles = 0;
8908         rsurface.batchvertex3f  = NULL;
8909         rsurface.batchvertex3f_vertexbuffer = NULL;
8910         rsurface.batchvertex3f_bufferoffset = 0;
8911         rsurface.batchsvector3f = NULL;
8912         rsurface.batchsvector3f_vertexbuffer = NULL;
8913         rsurface.batchsvector3f_bufferoffset = 0;
8914         rsurface.batchtvector3f = NULL;
8915         rsurface.batchtvector3f_vertexbuffer = NULL;
8916         rsurface.batchtvector3f_bufferoffset = 0;
8917         rsurface.batchnormal3f  = NULL;
8918         rsurface.batchnormal3f_vertexbuffer = NULL;
8919         rsurface.batchnormal3f_bufferoffset = 0;
8920         rsurface.batchlightmapcolor4f = NULL;
8921         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8922         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8923         rsurface.batchtexcoordtexture2f = NULL;
8924         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8925         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8926         rsurface.batchtexcoordlightmap2f = NULL;
8927         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8928         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8929         rsurface.batchskeletalindex4ub = NULL;
8930         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8931         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8932         rsurface.batchskeletalweight4ub = NULL;
8933         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8934         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8935         rsurface.batchvertexmesh = NULL;
8936         rsurface.batchvertexmesh_vertexbuffer = NULL;
8937         rsurface.batchvertexmesh_bufferoffset = 0;
8938         rsurface.batchelement3i = NULL;
8939         rsurface.batchelement3i_indexbuffer = NULL;
8940         rsurface.batchelement3i_bufferoffset = 0;
8941         rsurface.batchelement3s = NULL;
8942         rsurface.batchelement3s_indexbuffer = NULL;
8943         rsurface.batchelement3s_bufferoffset = 0;
8944         rsurface.passcolor4f = NULL;
8945         rsurface.passcolor4f_vertexbuffer = NULL;
8946         rsurface.passcolor4f_bufferoffset = 0;
8947         rsurface.forcecurrenttextureupdate = true;
8948
8949         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8950         {
8951                 if ((wantnormals || wanttangents) && !normal3f)
8952                 {
8953                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8954                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8955                 }
8956                 if (wanttangents && !svector3f)
8957                 {
8958                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8959                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8960                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8961                 }
8962         }
8963 }
8964
8965 float RSurf_FogPoint(const float *v)
8966 {
8967         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8968         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8969         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8970         float FogHeightFade = r_refdef.fogheightfade;
8971         float fogfrac;
8972         unsigned int fogmasktableindex;
8973         if (r_refdef.fogplaneviewabove)
8974                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8975         else
8976                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8977         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8978         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8979 }
8980
8981 float RSurf_FogVertex(const float *v)
8982 {
8983         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8984         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8985         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8986         float FogHeightFade = rsurface.fogheightfade;
8987         float fogfrac;
8988         unsigned int fogmasktableindex;
8989         if (r_refdef.fogplaneviewabove)
8990                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8991         else
8992                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8993         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8994         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8995 }
8996
8997 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8998 {
8999         int i;
9000         for (i = 0;i < numelements;i++)
9001                 outelement3i[i] = inelement3i[i] + adjust;
9002 }
9003
9004 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9005 extern cvar_t gl_vbo;
9006 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9007 {
9008         int deformindex;
9009         int firsttriangle;
9010         int numtriangles;
9011         int firstvertex;
9012         int endvertex;
9013         int numvertices;
9014         int surfacefirsttriangle;
9015         int surfacenumtriangles;
9016         int surfacefirstvertex;
9017         int surfaceendvertex;
9018         int surfacenumvertices;
9019         int batchnumsurfaces = texturenumsurfaces;
9020         int batchnumvertices;
9021         int batchnumtriangles;
9022         int needsupdate;
9023         int i, j;
9024         qboolean gaps;
9025         qboolean dynamicvertex;
9026         float amplitude;
9027         float animpos;
9028         float scale;
9029         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9030         float waveparms[4];
9031         unsigned char *ub;
9032         q3shaderinfo_deform_t *deform;
9033         const msurface_t *surface, *firstsurface;
9034         r_vertexmesh_t *vertexmesh;
9035         if (!texturenumsurfaces)
9036                 return;
9037         // find vertex range of this surface batch
9038         gaps = false;
9039         firstsurface = texturesurfacelist[0];
9040         firsttriangle = firstsurface->num_firsttriangle;
9041         batchnumvertices = 0;
9042         batchnumtriangles = 0;
9043         firstvertex = endvertex = firstsurface->num_firstvertex;
9044         for (i = 0;i < texturenumsurfaces;i++)
9045         {
9046                 surface = texturesurfacelist[i];
9047                 if (surface != firstsurface + i)
9048                         gaps = true;
9049                 surfacefirstvertex = surface->num_firstvertex;
9050                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9051                 surfacenumvertices = surface->num_vertices;
9052                 surfacenumtriangles = surface->num_triangles;
9053                 if (firstvertex > surfacefirstvertex)
9054                         firstvertex = surfacefirstvertex;
9055                 if (endvertex < surfaceendvertex)
9056                         endvertex = surfaceendvertex;
9057                 batchnumvertices += surfacenumvertices;
9058                 batchnumtriangles += surfacenumtriangles;
9059         }
9060
9061         r_refdef.stats[r_stat_batch_batches]++;
9062         if (gaps)
9063                 r_refdef.stats[r_stat_batch_withgaps]++;
9064         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9065         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9066         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9067
9068         // we now know the vertex range used, and if there are any gaps in it
9069         rsurface.batchfirstvertex = firstvertex;
9070         rsurface.batchnumvertices = endvertex - firstvertex;
9071         rsurface.batchfirsttriangle = firsttriangle;
9072         rsurface.batchnumtriangles = batchnumtriangles;
9073
9074         // this variable holds flags for which properties have been updated that
9075         // may require regenerating vertexmesh array...
9076         needsupdate = 0;
9077
9078         // check if any dynamic vertex processing must occur
9079         dynamicvertex = false;
9080
9081         // a cvar to force the dynamic vertex path to be taken, for debugging
9082         if (r_batch_debugdynamicvertexpath.integer)
9083         {
9084                 if (!dynamicvertex)
9085                 {
9086                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9087                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9088                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9089                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9090                 }
9091                 dynamicvertex = true;
9092         }
9093
9094         // if there is a chance of animated vertex colors, it's a dynamic batch
9095         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9096         {
9097                 if (!dynamicvertex)
9098                 {
9099                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9100                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9101                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9102                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9103                 }
9104                 dynamicvertex = true;
9105                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9106         }
9107
9108         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9109         {
9110                 switch (deform->deform)
9111                 {
9112                 default:
9113                 case Q3DEFORM_PROJECTIONSHADOW:
9114                 case Q3DEFORM_TEXT0:
9115                 case Q3DEFORM_TEXT1:
9116                 case Q3DEFORM_TEXT2:
9117                 case Q3DEFORM_TEXT3:
9118                 case Q3DEFORM_TEXT4:
9119                 case Q3DEFORM_TEXT5:
9120                 case Q3DEFORM_TEXT6:
9121                 case Q3DEFORM_TEXT7:
9122                 case Q3DEFORM_NONE:
9123                         break;
9124                 case Q3DEFORM_AUTOSPRITE:
9125                         if (!dynamicvertex)
9126                         {
9127                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9128                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9129                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9130                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9131                         }
9132                         dynamicvertex = true;
9133                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9134                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9135                         break;
9136                 case Q3DEFORM_AUTOSPRITE2:
9137                         if (!dynamicvertex)
9138                         {
9139                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9140                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9141                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9142                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9143                         }
9144                         dynamicvertex = true;
9145                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9146                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9147                         break;
9148                 case Q3DEFORM_NORMAL:
9149                         if (!dynamicvertex)
9150                         {
9151                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9152                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9153                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9154                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9155                         }
9156                         dynamicvertex = true;
9157                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9158                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9159                         break;
9160                 case Q3DEFORM_WAVE:
9161                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9162                                 break; // if wavefunc is a nop, ignore this transform
9163                         if (!dynamicvertex)
9164                         {
9165                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9166                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9167                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9168                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9169                         }
9170                         dynamicvertex = true;
9171                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9172                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9173                         break;
9174                 case Q3DEFORM_BULGE:
9175                         if (!dynamicvertex)
9176                         {
9177                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9178                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9179                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9180                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9181                         }
9182                         dynamicvertex = true;
9183                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9184                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9185                         break;
9186                 case Q3DEFORM_MOVE:
9187                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9188                                 break; // if wavefunc is a nop, ignore this transform
9189                         if (!dynamicvertex)
9190                         {
9191                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9192                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9193                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9194                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9195                         }
9196                         dynamicvertex = true;
9197                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9198                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9199                         break;
9200                 }
9201         }
9202         switch(rsurface.texture->tcgen.tcgen)
9203         {
9204         default:
9205         case Q3TCGEN_TEXTURE:
9206                 break;
9207         case Q3TCGEN_LIGHTMAP:
9208                 if (!dynamicvertex)
9209                 {
9210                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9211                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9212                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9213                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9214                 }
9215                 dynamicvertex = true;
9216                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9217                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9218                 break;
9219         case Q3TCGEN_VECTOR:
9220                 if (!dynamicvertex)
9221                 {
9222                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9223                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9224                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9225                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9226                 }
9227                 dynamicvertex = true;
9228                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9229                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9230                 break;
9231         case Q3TCGEN_ENVIRONMENT:
9232                 if (!dynamicvertex)
9233                 {
9234                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9235                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9236                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9237                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9238                 }
9239                 dynamicvertex = true;
9240                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9241                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9242                 break;
9243         }
9244         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9245         {
9246                 if (!dynamicvertex)
9247                 {
9248                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9249                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9250                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9251                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9252                 }
9253                 dynamicvertex = true;
9254                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9255                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9256         }
9257
9258         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9259         {
9260                 if (!dynamicvertex)
9261                 {
9262                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9263                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9264                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9265                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9266                 }
9267                 dynamicvertex = true;
9268                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9269         }
9270
9271         // when the model data has no vertex buffer (dynamic mesh), we need to
9272         // eliminate gaps
9273         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9274                 batchneed |= BATCHNEED_NOGAPS;
9275
9276         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9277         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9278         // we ensure this by treating the vertex batch as dynamic...
9279         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9280         {
9281                 if (!dynamicvertex)
9282                 {
9283                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9284                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9285                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9286                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9287                 }
9288                 dynamicvertex = true;
9289         }
9290
9291         if (dynamicvertex)
9292         {
9293                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9294                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9295                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9296                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9297                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9298                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9299                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9300                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9301         }
9302
9303         // if needsupdate, we have to do a dynamic vertex batch for sure
9304         if (needsupdate & batchneed)
9305         {
9306                 if (!dynamicvertex)
9307                 {
9308                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9309                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9310                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9311                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9312                 }
9313                 dynamicvertex = true;
9314         }
9315
9316         // see if we need to build vertexmesh from arrays
9317         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9318         {
9319                 if (!dynamicvertex)
9320                 {
9321                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9322                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9323                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9324                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9325                 }
9326                 dynamicvertex = true;
9327         }
9328
9329         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9330         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9331                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9332
9333         rsurface.batchvertex3f = rsurface.modelvertex3f;
9334         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9335         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9336         rsurface.batchsvector3f = rsurface.modelsvector3f;
9337         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9338         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9339         rsurface.batchtvector3f = rsurface.modeltvector3f;
9340         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9341         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9342         rsurface.batchnormal3f = rsurface.modelnormal3f;
9343         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9344         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9345         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9346         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9347         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9348         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9349         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9350         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9351         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9352         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9353         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9354         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9355         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9356         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9357         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9358         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9359         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9360         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9361         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9362         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9363         rsurface.batchelement3i = rsurface.modelelement3i;
9364         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9365         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9366         rsurface.batchelement3s = rsurface.modelelement3s;
9367         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9368         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9369         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9370         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9371         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9372         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9373         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9374
9375         // if any dynamic vertex processing has to occur in software, we copy the
9376         // entire surface list together before processing to rebase the vertices
9377         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9378         //
9379         // if any gaps exist and we do not have a static vertex buffer, we have to
9380         // copy the surface list together to avoid wasting upload bandwidth on the
9381         // vertices in the gaps.
9382         //
9383         // if gaps exist and we have a static vertex buffer, we can choose whether
9384         // to combine the index buffer ranges into one dynamic index buffer or
9385         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9386         //
9387         // in many cases the batch is reduced to one draw call.
9388
9389         rsurface.batchmultidraw = false;
9390         rsurface.batchmultidrawnumsurfaces = 0;
9391         rsurface.batchmultidrawsurfacelist = NULL;
9392
9393         if (!dynamicvertex)
9394         {
9395                 // static vertex data, just set pointers...
9396                 rsurface.batchgeneratedvertex = false;
9397                 // if there are gaps, we want to build a combined index buffer,
9398                 // otherwise use the original static buffer with an appropriate offset
9399                 if (gaps)
9400                 {
9401                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9402                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9403                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9404                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9405                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9406                         {
9407                                 rsurface.batchmultidraw = true;
9408                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9409                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9410                                 return;
9411                         }
9412                         // build a new triangle elements array for this batch
9413                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9414                         rsurface.batchfirsttriangle = 0;
9415                         numtriangles = 0;
9416                         for (i = 0;i < texturenumsurfaces;i++)
9417                         {
9418                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9419                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9420                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9421                                 numtriangles += surfacenumtriangles;
9422                         }
9423                         rsurface.batchelement3i_indexbuffer = NULL;
9424                         rsurface.batchelement3i_bufferoffset = 0;
9425                         rsurface.batchelement3s = NULL;
9426                         rsurface.batchelement3s_indexbuffer = NULL;
9427                         rsurface.batchelement3s_bufferoffset = 0;
9428                         if (endvertex <= 65536)
9429                         {
9430                                 // make a 16bit (unsigned short) index array if possible
9431                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9432                                 for (i = 0;i < numtriangles*3;i++)
9433                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9434                         }
9435                         // upload buffer data for the copytriangles batch
9436                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9437                         {
9438                                 if (rsurface.batchelement3s)
9439                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9440                                 else if (rsurface.batchelement3i)
9441                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9442                         }
9443                 }
9444                 else
9445                 {
9446                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9447                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9448                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9449                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9450                 }
9451                 return;
9452         }
9453
9454         // something needs software processing, do it for real...
9455         // we only directly handle separate array data in this case and then
9456         // generate interleaved data if needed...
9457         rsurface.batchgeneratedvertex = true;
9458         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9459         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9460         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9461         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9462
9463         // now copy the vertex data into a combined array and make an index array
9464         // (this is what Quake3 does all the time)
9465         // we also apply any skeletal animation here that would have been done in
9466         // the vertex shader, because most of the dynamic vertex animation cases
9467         // need actual vertex positions and normals
9468         //if (dynamicvertex)
9469         {
9470                 rsurface.batchvertexmesh = NULL;
9471                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9472                 rsurface.batchvertexmesh_bufferoffset = 0;
9473                 rsurface.batchvertex3f = NULL;
9474                 rsurface.batchvertex3f_vertexbuffer = NULL;
9475                 rsurface.batchvertex3f_bufferoffset = 0;
9476                 rsurface.batchsvector3f = NULL;
9477                 rsurface.batchsvector3f_vertexbuffer = NULL;
9478                 rsurface.batchsvector3f_bufferoffset = 0;
9479                 rsurface.batchtvector3f = NULL;
9480                 rsurface.batchtvector3f_vertexbuffer = NULL;
9481                 rsurface.batchtvector3f_bufferoffset = 0;
9482                 rsurface.batchnormal3f = NULL;
9483                 rsurface.batchnormal3f_vertexbuffer = NULL;
9484                 rsurface.batchnormal3f_bufferoffset = 0;
9485                 rsurface.batchlightmapcolor4f = NULL;
9486                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9487                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9488                 rsurface.batchtexcoordtexture2f = NULL;
9489                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9490                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9491                 rsurface.batchtexcoordlightmap2f = NULL;
9492                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9493                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9494                 rsurface.batchskeletalindex4ub = NULL;
9495                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9496                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9497                 rsurface.batchskeletalweight4ub = NULL;
9498                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9499                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9500                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9501                 rsurface.batchelement3i_indexbuffer = NULL;
9502                 rsurface.batchelement3i_bufferoffset = 0;
9503                 rsurface.batchelement3s = NULL;
9504                 rsurface.batchelement3s_indexbuffer = NULL;
9505                 rsurface.batchelement3s_bufferoffset = 0;
9506                 rsurface.batchskeletaltransform3x4buffer = NULL;
9507                 rsurface.batchskeletaltransform3x4offset = 0;
9508                 rsurface.batchskeletaltransform3x4size = 0;
9509                 // we'll only be setting up certain arrays as needed
9510                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9511                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9512                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9513                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9514                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9515                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9516                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9517                 {
9518                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9519                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9520                 }
9521                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9522                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9523                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9524                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9525                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9526                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9527                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9528                 {
9529                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9530                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9531                 }
9532                 numvertices = 0;
9533                 numtriangles = 0;
9534                 for (i = 0;i < texturenumsurfaces;i++)
9535                 {
9536                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9537                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9538                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9539                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9540                         // copy only the data requested
9541                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9542                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9543                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9544                         {
9545                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9546                                 {
9547                                         if (rsurface.batchvertex3f)
9548                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9549                                         else
9550                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9551                                 }
9552                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9553                                 {
9554                                         if (rsurface.modelnormal3f)
9555                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9556                                         else
9557                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9558                                 }
9559                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9560                                 {
9561                                         if (rsurface.modelsvector3f)
9562                                         {
9563                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9564                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9565                                         }
9566                                         else
9567                                         {
9568                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9569                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9570                                         }
9571                                 }
9572                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9573                                 {
9574                                         if (rsurface.modellightmapcolor4f)
9575                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9576                                         else
9577                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9578                                 }
9579                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9580                                 {
9581                                         if (rsurface.modeltexcoordtexture2f)
9582                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9583                                         else
9584                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9585                                 }
9586                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9587                                 {
9588                                         if (rsurface.modeltexcoordlightmap2f)
9589                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9590                                         else
9591                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9592                                 }
9593                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9594                                 {
9595                                         if (rsurface.modelskeletalindex4ub)
9596                                         {
9597                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9598                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9599                                         }
9600                                         else
9601                                         {
9602                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9603                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9604                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9605                                                 for (j = 0;j < surfacenumvertices;j++)
9606                                                         ub[j*4] = 255;
9607                                         }
9608                                 }
9609                         }
9610                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9611                         numvertices += surfacenumvertices;
9612                         numtriangles += surfacenumtriangles;
9613                 }
9614
9615                 // generate a 16bit index array as well if possible
9616                 // (in general, dynamic batches fit)
9617                 if (numvertices <= 65536)
9618                 {
9619                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9620                         for (i = 0;i < numtriangles*3;i++)
9621                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9622                 }
9623
9624                 // since we've copied everything, the batch now starts at 0
9625                 rsurface.batchfirstvertex = 0;
9626                 rsurface.batchnumvertices = batchnumvertices;
9627                 rsurface.batchfirsttriangle = 0;
9628                 rsurface.batchnumtriangles = batchnumtriangles;
9629         }
9630
9631         // apply skeletal animation that would have been done in the vertex shader
9632         if (rsurface.batchskeletaltransform3x4)
9633         {
9634                 const unsigned char *si;
9635                 const unsigned char *sw;
9636                 const float *t[4];
9637                 const float *b = rsurface.batchskeletaltransform3x4;
9638                 float *vp, *vs, *vt, *vn;
9639                 float w[4];
9640                 float m[3][4], n[3][4];
9641                 float tp[3], ts[3], tt[3], tn[3];
9642                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9643                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9644                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9645                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9646                 si = rsurface.batchskeletalindex4ub;
9647                 sw = rsurface.batchskeletalweight4ub;
9648                 vp = rsurface.batchvertex3f;
9649                 vs = rsurface.batchsvector3f;
9650                 vt = rsurface.batchtvector3f;
9651                 vn = rsurface.batchnormal3f;
9652                 memset(m[0], 0, sizeof(m));
9653                 memset(n[0], 0, sizeof(n));
9654                 for (i = 0;i < batchnumvertices;i++)
9655                 {
9656                         t[0] = b + si[0]*12;
9657                         if (sw[0] == 255)
9658                         {
9659                                 // common case - only one matrix
9660                                 m[0][0] = t[0][ 0];
9661                                 m[0][1] = t[0][ 1];
9662                                 m[0][2] = t[0][ 2];
9663                                 m[0][3] = t[0][ 3];
9664                                 m[1][0] = t[0][ 4];
9665                                 m[1][1] = t[0][ 5];
9666                                 m[1][2] = t[0][ 6];
9667                                 m[1][3] = t[0][ 7];
9668                                 m[2][0] = t[0][ 8];
9669                                 m[2][1] = t[0][ 9];
9670                                 m[2][2] = t[0][10];
9671                                 m[2][3] = t[0][11];
9672                         }
9673                         else if (sw[2] + sw[3])
9674                         {
9675                                 // blend 4 matrices
9676                                 t[1] = b + si[1]*12;
9677                                 t[2] = b + si[2]*12;
9678                                 t[3] = b + si[3]*12;
9679                                 w[0] = sw[0] * (1.0f / 255.0f);
9680                                 w[1] = sw[1] * (1.0f / 255.0f);
9681                                 w[2] = sw[2] * (1.0f / 255.0f);
9682                                 w[3] = sw[3] * (1.0f / 255.0f);
9683                                 // blend the matrices
9684                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9685                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9686                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9687                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9688                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9689                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9690                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9691                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9692                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9693                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9694                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9695                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9696                         }
9697                         else
9698                         {
9699                                 // blend 2 matrices
9700                                 t[1] = b + si[1]*12;
9701                                 w[0] = sw[0] * (1.0f / 255.0f);
9702                                 w[1] = sw[1] * (1.0f / 255.0f);
9703                                 // blend the matrices
9704                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9705                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9706                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9707                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9708                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9709                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9710                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9711                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9712                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9713                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9714                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9715                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9716                         }
9717                         si += 4;
9718                         sw += 4;
9719                         // modify the vertex
9720                         VectorCopy(vp, tp);
9721                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9722                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9723                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9724                         vp += 3;
9725                         if (vn)
9726                         {
9727                                 // the normal transformation matrix is a set of cross products...
9728                                 CrossProduct(m[1], m[2], n[0]);
9729                                 CrossProduct(m[2], m[0], n[1]);
9730                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9731                                 VectorCopy(vn, tn);
9732                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9733                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9734                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9735                                 VectorNormalize(vn);
9736                                 vn += 3;
9737                                 if (vs)
9738                                 {
9739                                         VectorCopy(vs, ts);
9740                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9741                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9742                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9743                                         VectorNormalize(vs);
9744                                         vs += 3;
9745                                         VectorCopy(vt, tt);
9746                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9747                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9748                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9749                                         VectorNormalize(vt);
9750                                         vt += 3;
9751                                 }
9752                         }
9753                 }
9754                 rsurface.batchskeletaltransform3x4 = NULL;
9755                 rsurface.batchskeletalnumtransforms = 0;
9756         }
9757
9758         // q1bsp surfaces rendered in vertex color mode have to have colors
9759         // calculated based on lightstyles
9760         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9761         {
9762                 // generate color arrays for the surfaces in this list
9763                 int c[4];
9764                 int scale;
9765                 int size3;
9766                 const int *offsets;
9767                 const unsigned char *lm;
9768                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9769                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9770                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9771                 numvertices = 0;
9772                 for (i = 0;i < texturenumsurfaces;i++)
9773                 {
9774                         surface = texturesurfacelist[i];
9775                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9776                         surfacenumvertices = surface->num_vertices;
9777                         if (surface->lightmapinfo->samples)
9778                         {
9779                                 for (j = 0;j < surfacenumvertices;j++)
9780                                 {
9781                                         lm = surface->lightmapinfo->samples + offsets[j];
9782                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9783                                         VectorScale(lm, scale, c);
9784                                         if (surface->lightmapinfo->styles[1] != 255)
9785                                         {
9786                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9787                                                 lm += size3;
9788                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9789                                                 VectorMA(c, scale, lm, c);
9790                                                 if (surface->lightmapinfo->styles[2] != 255)
9791                                                 {
9792                                                         lm += size3;
9793                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9794                                                         VectorMA(c, scale, lm, c);
9795                                                         if (surface->lightmapinfo->styles[3] != 255)
9796                                                         {
9797                                                                 lm += size3;
9798                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9799                                                                 VectorMA(c, scale, lm, c);
9800                                                         }
9801                                                 }
9802                                         }
9803                                         c[0] >>= 7;
9804                                         c[1] >>= 7;
9805                                         c[2] >>= 7;
9806                                         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);
9807                                         numvertices++;
9808                                 }
9809                         }
9810                         else
9811                         {
9812                                 for (j = 0;j < surfacenumvertices;j++)
9813                                 {
9814                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9815                                         numvertices++;
9816                                 }
9817                         }
9818                 }
9819         }
9820
9821         // if vertices are deformed (sprite flares and things in maps, possibly
9822         // water waves, bulges and other deformations), modify the copied vertices
9823         // in place
9824         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9825         {
9826                 switch (deform->deform)
9827                 {
9828                 default:
9829                 case Q3DEFORM_PROJECTIONSHADOW:
9830                 case Q3DEFORM_TEXT0:
9831                 case Q3DEFORM_TEXT1:
9832                 case Q3DEFORM_TEXT2:
9833                 case Q3DEFORM_TEXT3:
9834                 case Q3DEFORM_TEXT4:
9835                 case Q3DEFORM_TEXT5:
9836                 case Q3DEFORM_TEXT6:
9837                 case Q3DEFORM_TEXT7:
9838                 case Q3DEFORM_NONE:
9839                         break;
9840                 case Q3DEFORM_AUTOSPRITE:
9841                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9842                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9843                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9844                         VectorNormalize(newforward);
9845                         VectorNormalize(newright);
9846                         VectorNormalize(newup);
9847 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9848 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9849 //                      rsurface.batchvertex3f_bufferoffset = 0;
9850 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9851 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9852 //                      rsurface.batchsvector3f_bufferoffset = 0;
9853 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9854 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9855 //                      rsurface.batchtvector3f_bufferoffset = 0;
9856 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9857 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9858 //                      rsurface.batchnormal3f_bufferoffset = 0;
9859                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9860                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9861                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9862                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9863                                 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);
9864                         // a single autosprite surface can contain multiple sprites...
9865                         for (j = 0;j < batchnumvertices - 3;j += 4)
9866                         {
9867                                 VectorClear(center);
9868                                 for (i = 0;i < 4;i++)
9869                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9870                                 VectorScale(center, 0.25f, center);
9871                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9872                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9873                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9874                                 for (i = 0;i < 4;i++)
9875                                 {
9876                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9877                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9878                                 }
9879                         }
9880                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9881                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9882                         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);
9883                         break;
9884                 case Q3DEFORM_AUTOSPRITE2:
9885                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9886                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9887                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9888                         VectorNormalize(newforward);
9889                         VectorNormalize(newright);
9890                         VectorNormalize(newup);
9891 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9892 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9893 //                      rsurface.batchvertex3f_bufferoffset = 0;
9894                         {
9895                                 const float *v1, *v2;
9896                                 vec3_t start, end;
9897                                 float f, l;
9898                                 struct
9899                                 {
9900                                         float length2;
9901                                         const float *v1;
9902                                         const float *v2;
9903                                 }
9904                                 shortest[2];
9905                                 memset(shortest, 0, sizeof(shortest));
9906                                 // a single autosprite surface can contain multiple sprites...
9907                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9908                                 {
9909                                         VectorClear(center);
9910                                         for (i = 0;i < 4;i++)
9911                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9912                                         VectorScale(center, 0.25f, center);
9913                                         // find the two shortest edges, then use them to define the
9914                                         // axis vectors for rotating around the central axis
9915                                         for (i = 0;i < 6;i++)
9916                                         {
9917                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9918                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9919                                                 l = VectorDistance2(v1, v2);
9920                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9921                                                 if (v1[2] != v2[2])
9922                                                         l += (1.0f / 1024.0f);
9923                                                 if (shortest[0].length2 > l || i == 0)
9924                                                 {
9925                                                         shortest[1] = shortest[0];
9926                                                         shortest[0].length2 = l;
9927                                                         shortest[0].v1 = v1;
9928                                                         shortest[0].v2 = v2;
9929                                                 }
9930                                                 else if (shortest[1].length2 > l || i == 1)
9931                                                 {
9932                                                         shortest[1].length2 = l;
9933                                                         shortest[1].v1 = v1;
9934                                                         shortest[1].v2 = v2;
9935                                                 }
9936                                         }
9937                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9938                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9939                                         // this calculates the right vector from the shortest edge
9940                                         // and the up vector from the edge midpoints
9941                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9942                                         VectorNormalize(right);
9943                                         VectorSubtract(end, start, up);
9944                                         VectorNormalize(up);
9945                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9946                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9947                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9948                                         VectorNegate(forward, forward);
9949                                         VectorReflect(forward, 0, up, forward);
9950                                         VectorNormalize(forward);
9951                                         CrossProduct(up, forward, newright);
9952                                         VectorNormalize(newright);
9953                                         // rotate the quad around the up axis vector, this is made
9954                                         // especially easy by the fact we know the quad is flat,
9955                                         // so we only have to subtract the center position and
9956                                         // measure distance along the right vector, and then
9957                                         // multiply that by the newright vector and add back the
9958                                         // center position
9959                                         // we also need to subtract the old position to undo the
9960                                         // displacement from the center, which we do with a
9961                                         // DotProduct, the subtraction/addition of center is also
9962                                         // optimized into DotProducts here
9963                                         l = DotProduct(right, center);
9964                                         for (i = 0;i < 4;i++)
9965                                         {
9966                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9967                                                 f = DotProduct(right, v1) - l;
9968                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9969                                         }
9970                                 }
9971                         }
9972                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9973                         {
9974 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9975 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9976 //                              rsurface.batchnormal3f_bufferoffset = 0;
9977                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9978                         }
9979                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9980                         {
9981 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9982 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9983 //                              rsurface.batchsvector3f_bufferoffset = 0;
9984 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9985 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9986 //                              rsurface.batchtvector3f_bufferoffset = 0;
9987                                 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);
9988                         }
9989                         break;
9990                 case Q3DEFORM_NORMAL:
9991                         // deform the normals to make reflections wavey
9992                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9993                         rsurface.batchnormal3f_vertexbuffer = NULL;
9994                         rsurface.batchnormal3f_bufferoffset = 0;
9995                         for (j = 0;j < batchnumvertices;j++)
9996                         {
9997                                 float vertex[3];
9998                                 float *normal = rsurface.batchnormal3f + 3*j;
9999                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10000                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10001                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10002                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10003                                 VectorNormalize(normal);
10004                         }
10005                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10006                         {
10007 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10008 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10009 //                              rsurface.batchsvector3f_bufferoffset = 0;
10010 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10011 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10012 //                              rsurface.batchtvector3f_bufferoffset = 0;
10013                                 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);
10014                         }
10015                         break;
10016                 case Q3DEFORM_WAVE:
10017                         // deform vertex array to make wavey water and flags and such
10018                         waveparms[0] = deform->waveparms[0];
10019                         waveparms[1] = deform->waveparms[1];
10020                         waveparms[2] = deform->waveparms[2];
10021                         waveparms[3] = deform->waveparms[3];
10022                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10023                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10024                         // this is how a divisor of vertex influence on deformation
10025                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10026                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10027 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10028 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10029 //                      rsurface.batchvertex3f_bufferoffset = 0;
10030 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10031 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10032 //                      rsurface.batchnormal3f_bufferoffset = 0;
10033                         for (j = 0;j < batchnumvertices;j++)
10034                         {
10035                                 // if the wavefunc depends on time, evaluate it per-vertex
10036                                 if (waveparms[3])
10037                                 {
10038                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10039                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10040                                 }
10041                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10042                         }
10043                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10044                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10045                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10046                         {
10047 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10048 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10049 //                              rsurface.batchsvector3f_bufferoffset = 0;
10050 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10051 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10052 //                              rsurface.batchtvector3f_bufferoffset = 0;
10053                                 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);
10054                         }
10055                         break;
10056                 case Q3DEFORM_BULGE:
10057                         // deform vertex array to make the surface have moving bulges
10058 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10059 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10060 //                      rsurface.batchvertex3f_bufferoffset = 0;
10061 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10062 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10063 //                      rsurface.batchnormal3f_bufferoffset = 0;
10064                         for (j = 0;j < batchnumvertices;j++)
10065                         {
10066                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10067                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10068                         }
10069                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10070                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10071                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10072                         {
10073 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10074 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10075 //                              rsurface.batchsvector3f_bufferoffset = 0;
10076 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10077 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10078 //                              rsurface.batchtvector3f_bufferoffset = 0;
10079                                 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);
10080                         }
10081                         break;
10082                 case Q3DEFORM_MOVE:
10083                         // deform vertex array
10084                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10085                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10086                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10087                         VectorScale(deform->parms, scale, waveparms);
10088 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10089 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10090 //                      rsurface.batchvertex3f_bufferoffset = 0;
10091                         for (j = 0;j < batchnumvertices;j++)
10092                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10093                         break;
10094                 }
10095         }
10096
10097         if (rsurface.batchtexcoordtexture2f)
10098         {
10099         // generate texcoords based on the chosen texcoord source
10100                 switch(rsurface.texture->tcgen.tcgen)
10101                 {
10102                 default:
10103                 case Q3TCGEN_TEXTURE:
10104                         break;
10105                 case Q3TCGEN_LIGHTMAP:
10106         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10107         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10108         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10109                         if (rsurface.batchtexcoordlightmap2f)
10110                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10111                         break;
10112                 case Q3TCGEN_VECTOR:
10113         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10114         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10115         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10116                         for (j = 0;j < batchnumvertices;j++)
10117                         {
10118                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10119                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10120                         }
10121                         break;
10122                 case Q3TCGEN_ENVIRONMENT:
10123                         // make environment reflections using a spheremap
10124                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10125                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10126                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10127                         for (j = 0;j < batchnumvertices;j++)
10128                         {
10129                                 // identical to Q3A's method, but executed in worldspace so
10130                                 // carried models can be shiny too
10131
10132                                 float viewer[3], d, reflected[3], worldreflected[3];
10133
10134                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10135                                 // VectorNormalize(viewer);
10136
10137                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10138
10139                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10140                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10141                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10142                                 // note: this is proportinal to viewer, so we can normalize later
10143
10144                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10145                                 VectorNormalize(worldreflected);
10146
10147                                 // note: this sphere map only uses world x and z!
10148                                 // so positive and negative y will LOOK THE SAME.
10149                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10150                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10151                         }
10152                         break;
10153                 }
10154                 // the only tcmod that needs software vertex processing is turbulent, so
10155                 // check for it here and apply the changes if needed
10156                 // and we only support that as the first one
10157                 // (handling a mixture of turbulent and other tcmods would be problematic
10158                 //  without punting it entirely to a software path)
10159                 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10160                 {
10161                         amplitude = rsurface.texture->tcmods[0].parms[1];
10162                         animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10163         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10164         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10165         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10166                         for (j = 0;j < batchnumvertices;j++)
10167                         {
10168                                 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);
10169                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10170                         }
10171                 }
10172         }
10173
10174         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10175         {
10176                 // convert the modified arrays to vertex structs
10177 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10178 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10179 //              rsurface.batchvertexmesh_bufferoffset = 0;
10180                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10181                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10182                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10183                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10184                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10185                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10186                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10187                 {
10188                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10189                         {
10190                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10191                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10192                         }
10193                 }
10194                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10195                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10196                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10197                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10198                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10199                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10200                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10201                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10202                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10203                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10204                 {
10205                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10206                         {
10207                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10208                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10209                         }
10210                 }
10211         }
10212
10213         // upload buffer data for the dynamic batch
10214         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10215         {
10216                 if (rsurface.batchvertexmesh)
10217                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10218                 else
10219                 {
10220                         if (rsurface.batchvertex3f)
10221                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10222                         if (rsurface.batchsvector3f)
10223                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10224                         if (rsurface.batchtvector3f)
10225                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10226                         if (rsurface.batchnormal3f)
10227                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10228                         if (rsurface.batchlightmapcolor4f)
10229                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10230                         if (rsurface.batchtexcoordtexture2f)
10231                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10232                         if (rsurface.batchtexcoordlightmap2f)
10233                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10234                         if (rsurface.batchskeletalindex4ub)
10235                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10236                         if (rsurface.batchskeletalweight4ub)
10237                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10238                 }
10239                 if (rsurface.batchelement3s)
10240                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10241                 else if (rsurface.batchelement3i)
10242                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10243         }
10244 }
10245
10246 void RSurf_DrawBatch(void)
10247 {
10248         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10249         // through the pipeline, killing it earlier in the pipeline would have
10250         // per-surface overhead rather than per-batch overhead, so it's best to
10251         // reject it here, before it hits glDraw.
10252         if (rsurface.batchnumtriangles == 0)
10253                 return;
10254 #if 0
10255         // batch debugging code
10256         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10257         {
10258                 int i;
10259                 int j;
10260                 int c;
10261                 const int *e;
10262                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10263                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10264                 {
10265                         c = e[i];
10266                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10267                         {
10268                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10269                                 {
10270                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10271                                                 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);
10272                                         break;
10273                                 }
10274                         }
10275                 }
10276         }
10277 #endif
10278         if (rsurface.batchmultidraw)
10279         {
10280                 // issue multiple draws rather than copying index data
10281                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10282                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10283                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10284                 for (i = 0;i < numsurfaces;)
10285                 {
10286                         // combine consecutive surfaces as one draw
10287                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10288                                 if (surfacelist[j] != surfacelist[k] + 1)
10289                                         break;
10290                         firstvertex = surfacelist[i]->num_firstvertex;
10291                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10292                         firsttriangle = surfacelist[i]->num_firsttriangle;
10293                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10294                         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);
10295                         i = j;
10296                 }
10297         }
10298         else
10299         {
10300                 // there is only one consecutive run of index data (may have been combined)
10301                 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);
10302         }
10303 }
10304
10305 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10306 {
10307         // pick the closest matching water plane
10308         int planeindex, vertexindex, bestplaneindex = -1;
10309         float d, bestd;
10310         vec3_t vert;
10311         const float *v;
10312         r_waterstate_waterplane_t *p;
10313         qboolean prepared = false;
10314         bestd = 0;
10315         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10316         {
10317                 if(p->camera_entity != rsurface.texture->camera_entity)
10318                         continue;
10319                 d = 0;
10320                 if(!prepared)
10321                 {
10322                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10323                         prepared = true;
10324                         if(rsurface.batchnumvertices == 0)
10325                                 break;
10326                 }
10327                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10328                 {
10329                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10330                         d += fabs(PlaneDiff(vert, &p->plane));
10331                 }
10332                 if (bestd > d || bestplaneindex < 0)
10333                 {
10334                         bestd = d;
10335                         bestplaneindex = planeindex;
10336                 }
10337         }
10338         return bestplaneindex;
10339         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10340         // this situation though, as it might be better to render single larger
10341         // batches with useless stuff (backface culled for example) than to
10342         // render multiple smaller batches
10343 }
10344
10345 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10346 {
10347         int i;
10348         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10349         rsurface.passcolor4f_vertexbuffer = 0;
10350         rsurface.passcolor4f_bufferoffset = 0;
10351         for (i = 0;i < rsurface.batchnumvertices;i++)
10352                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10353 }
10354
10355 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10356 {
10357         int i;
10358         float f;
10359         const float *v;
10360         const float *c;
10361         float *c2;
10362         if (rsurface.passcolor4f)
10363         {
10364                 // generate color arrays
10365                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10366                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10367                 rsurface.passcolor4f_vertexbuffer = 0;
10368                 rsurface.passcolor4f_bufferoffset = 0;
10369                 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)
10370                 {
10371                         f = RSurf_FogVertex(v);
10372                         c2[0] = c[0] * f;
10373                         c2[1] = c[1] * f;
10374                         c2[2] = c[2] * f;
10375                         c2[3] = c[3];
10376                 }
10377         }
10378         else
10379         {
10380                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10381                 rsurface.passcolor4f_vertexbuffer = 0;
10382                 rsurface.passcolor4f_bufferoffset = 0;
10383                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10384                 {
10385                         f = RSurf_FogVertex(v);
10386                         c2[0] = f;
10387                         c2[1] = f;
10388                         c2[2] = f;
10389                         c2[3] = 1;
10390                 }
10391         }
10392 }
10393
10394 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10395 {
10396         int i;
10397         float f;
10398         const float *v;
10399         const float *c;
10400         float *c2;
10401         if (!rsurface.passcolor4f)
10402                 return;
10403         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10404         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10405         rsurface.passcolor4f_vertexbuffer = 0;
10406         rsurface.passcolor4f_bufferoffset = 0;
10407         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)
10408         {
10409                 f = RSurf_FogVertex(v);
10410                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10411                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10412                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10413                 c2[3] = c[3];
10414         }
10415 }
10416
10417 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10418 {
10419         int i;
10420         const float *c;
10421         float *c2;
10422         if (!rsurface.passcolor4f)
10423                 return;
10424         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10425         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10426         rsurface.passcolor4f_vertexbuffer = 0;
10427         rsurface.passcolor4f_bufferoffset = 0;
10428         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10429         {
10430                 c2[0] = c[0] * r;
10431                 c2[1] = c[1] * g;
10432                 c2[2] = c[2] * b;
10433                 c2[3] = c[3] * a;
10434         }
10435 }
10436
10437 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10438 {
10439         int i;
10440         const float *c;
10441         float *c2;
10442         if (!rsurface.passcolor4f)
10443                 return;
10444         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10445         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10446         rsurface.passcolor4f_vertexbuffer = 0;
10447         rsurface.passcolor4f_bufferoffset = 0;
10448         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10449         {
10450                 c2[0] = c[0] + r_refdef.scene.ambient;
10451                 c2[1] = c[1] + r_refdef.scene.ambient;
10452                 c2[2] = c[2] + r_refdef.scene.ambient;
10453                 c2[3] = c[3];
10454         }
10455 }
10456
10457 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10458 {
10459         // TODO: optimize
10460         rsurface.passcolor4f = NULL;
10461         rsurface.passcolor4f_vertexbuffer = 0;
10462         rsurface.passcolor4f_bufferoffset = 0;
10463         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10464         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10465         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10466         GL_Color(r, g, b, a);
10467         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10468         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10469         R_Mesh_TexMatrix(0, NULL);
10470         RSurf_DrawBatch();
10471 }
10472
10473 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10474 {
10475         // TODO: optimize applyfog && applycolor case
10476         // just apply fog if necessary, and tint the fog color array if necessary
10477         rsurface.passcolor4f = NULL;
10478         rsurface.passcolor4f_vertexbuffer = 0;
10479         rsurface.passcolor4f_bufferoffset = 0;
10480         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10481         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10482         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10483         GL_Color(r, g, b, a);
10484         RSurf_DrawBatch();
10485 }
10486
10487 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10488 {
10489         // TODO: optimize
10490         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10491         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10492         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10493         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10494         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10495         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10496         GL_Color(r, g, b, a);
10497         RSurf_DrawBatch();
10498 }
10499
10500 static void RSurf_DrawBatch_GL11_ClampColor(void)
10501 {
10502         int i;
10503         const float *c1;
10504         float *c2;
10505         if (!rsurface.passcolor4f)
10506                 return;
10507         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10508         {
10509                 c2[0] = bound(0.0f, c1[0], 1.0f);
10510                 c2[1] = bound(0.0f, c1[1], 1.0f);
10511                 c2[2] = bound(0.0f, c1[2], 1.0f);
10512                 c2[3] = bound(0.0f, c1[3], 1.0f);
10513         }
10514 }
10515
10516 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10517 {
10518         int i;
10519         float f;
10520         const float *v;
10521         const float *n;
10522         float *c;
10523         //vec3_t eyedir;
10524
10525         // fake shading
10526         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10527         rsurface.passcolor4f_vertexbuffer = 0;
10528         rsurface.passcolor4f_bufferoffset = 0;
10529         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)
10530         {
10531                 f = -DotProduct(r_refdef.view.forward, n);
10532                 f = max(0, f);
10533                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10534                 f *= r_refdef.lightmapintensity;
10535                 Vector4Set(c, f, f, f, 1);
10536         }
10537 }
10538
10539 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10540 {
10541         RSurf_DrawBatch_GL11_ApplyFakeLight();
10542         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10543         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10544         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10545         GL_Color(r, g, b, a);
10546         RSurf_DrawBatch();
10547 }
10548
10549 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10550 {
10551         int i;
10552         float f;
10553         float alpha;
10554         const float *v;
10555         const float *n;
10556         float *c;
10557         vec3_t ambientcolor;
10558         vec3_t diffusecolor;
10559         vec3_t lightdir;
10560         // TODO: optimize
10561         // model lighting
10562         VectorCopy(rsurface.modellight_lightdir, lightdir);
10563         f = 0.5f * r_refdef.lightmapintensity;
10564         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10565         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10566         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10567         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10568         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10569         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10570         alpha = *a;
10571         if (VectorLength2(diffusecolor) > 0)
10572         {
10573                 // q3-style directional shading
10574                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10575                 rsurface.passcolor4f_vertexbuffer = 0;
10576                 rsurface.passcolor4f_bufferoffset = 0;
10577                 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)
10578                 {
10579                         if ((f = DotProduct(n, lightdir)) > 0)
10580                                 VectorMA(ambientcolor, f, diffusecolor, c);
10581                         else
10582                                 VectorCopy(ambientcolor, c);
10583                         c[3] = alpha;
10584                 }
10585                 *r = 1;
10586                 *g = 1;
10587                 *b = 1;
10588                 *a = 1;
10589                 *applycolor = false;
10590         }
10591         else
10592         {
10593                 *r = ambientcolor[0];
10594                 *g = ambientcolor[1];
10595                 *b = ambientcolor[2];
10596                 rsurface.passcolor4f = NULL;
10597                 rsurface.passcolor4f_vertexbuffer = 0;
10598                 rsurface.passcolor4f_bufferoffset = 0;
10599         }
10600 }
10601
10602 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10603 {
10604         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10605         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10606         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10607         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10608         GL_Color(r, g, b, a);
10609         RSurf_DrawBatch();
10610 }
10611
10612 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10613 {
10614         int i;
10615         float f;
10616         const float *v;
10617         float *c;
10618
10619         // fake shading
10620         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10621         rsurface.passcolor4f_vertexbuffer = 0;
10622         rsurface.passcolor4f_bufferoffset = 0;
10623
10624         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10625         {
10626                 f = 1 - RSurf_FogVertex(v);
10627                 c[0] = r;
10628                 c[1] = g;
10629                 c[2] = b;
10630                 c[3] = f * a;
10631         }
10632 }
10633
10634 void RSurf_SetupDepthAndCulling(void)
10635 {
10636         // submodels are biased to avoid z-fighting with world surfaces that they
10637         // may be exactly overlapping (avoids z-fighting artifacts on certain
10638         // doors and things in Quake maps)
10639         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10640         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10641         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10642         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10643 }
10644
10645 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10646 {
10647         // transparent sky would be ridiculous
10648         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10649                 return;
10650         R_SetupShader_Generic_NoTexture(false, false);
10651         skyrenderlater = true;
10652         RSurf_SetupDepthAndCulling();
10653         GL_DepthMask(true);
10654         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10655         // skymasking on them, and Quake3 never did sky masking (unlike
10656         // software Quake and software Quake2), so disable the sky masking
10657         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10658         // and skymasking also looks very bad when noclipping outside the
10659         // level, so don't use it then either.
10660         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10661         {
10662                 R_Mesh_ResetTextureState();
10663                 if (skyrendermasked)
10664                 {
10665                         R_SetupShader_DepthOrShadow(false, false, false);
10666                         // depth-only (masking)
10667                         GL_ColorMask(0,0,0,0);
10668                         // just to make sure that braindead drivers don't draw
10669                         // anything despite that colormask...
10670                         GL_BlendFunc(GL_ZERO, GL_ONE);
10671                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10672                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10673                 }
10674                 else
10675                 {
10676                         R_SetupShader_Generic_NoTexture(false, false);
10677                         // fog sky
10678                         GL_BlendFunc(GL_ONE, GL_ZERO);
10679                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10680                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10681                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10682                 }
10683                 RSurf_DrawBatch();
10684                 if (skyrendermasked)
10685                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10686         }
10687         R_Mesh_ResetTextureState();
10688         GL_Color(1, 1, 1, 1);
10689 }
10690
10691 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10692 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10693 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10694 {
10695         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10696                 return;
10697         if (prepass)
10698         {
10699                 // render screenspace normalmap to texture
10700                 GL_DepthMask(true);
10701                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10702                 RSurf_DrawBatch();
10703                 return;
10704         }
10705
10706         // bind lightmap texture
10707
10708         // water/refraction/reflection/camera surfaces have to be handled specially
10709         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10710         {
10711                 int start, end, startplaneindex;
10712                 for (start = 0;start < texturenumsurfaces;start = end)
10713                 {
10714                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10715                         if(startplaneindex < 0)
10716                         {
10717                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10718                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10719                                 end = start + 1;
10720                                 continue;
10721                         }
10722                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10723                                 ;
10724                         // now that we have a batch using the same planeindex, render it
10725                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10726                         {
10727                                 // render water or distortion background
10728                                 GL_DepthMask(true);
10729                                 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);
10730                                 RSurf_DrawBatch();
10731                                 // blend surface on top
10732                                 GL_DepthMask(false);
10733                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10734                                 RSurf_DrawBatch();
10735                         }
10736                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10737                         {
10738                                 // render surface with reflection texture as input
10739                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10740                                 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);
10741                                 RSurf_DrawBatch();
10742                         }
10743                 }
10744                 return;
10745         }
10746
10747         // render surface batch normally
10748         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10749         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);
10750         RSurf_DrawBatch();
10751 }
10752
10753 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10754 {
10755         // OpenGL 1.3 path - anything not completely ancient
10756         qboolean applycolor;
10757         qboolean applyfog;
10758         int layerindex;
10759         const texturelayer_t *layer;
10760         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);
10761         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10762
10763         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10764         {
10765                 vec4_t layercolor;
10766                 int layertexrgbscale;
10767                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10768                 {
10769                         if (layerindex == 0)
10770                                 GL_AlphaTest(true);
10771                         else
10772                         {
10773                                 GL_AlphaTest(false);
10774                                 GL_DepthFunc(GL_EQUAL);
10775                         }
10776                 }
10777                 GL_DepthMask(layer->depthmask && writedepth);
10778                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10779                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10780                 {
10781                         layertexrgbscale = 4;
10782                         VectorScale(layer->color, 0.25f, layercolor);
10783                 }
10784                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10785                 {
10786                         layertexrgbscale = 2;
10787                         VectorScale(layer->color, 0.5f, layercolor);
10788                 }
10789                 else
10790                 {
10791                         layertexrgbscale = 1;
10792                         VectorScale(layer->color, 1.0f, layercolor);
10793                 }
10794                 layercolor[3] = layer->color[3];
10795                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10796                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10797                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10798                 switch (layer->type)
10799                 {
10800                 case TEXTURELAYERTYPE_LITTEXTURE:
10801                         // single-pass lightmapped texture with 2x rgbscale
10802                         R_Mesh_TexBind(0, r_texture_white);
10803                         R_Mesh_TexMatrix(0, NULL);
10804                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10805                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10806                         R_Mesh_TexBind(1, layer->texture);
10807                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10808                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10809                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10810                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10811                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10812                         else if (FAKELIGHT_ENABLED)
10813                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10814                         else if (rsurface.uselightmaptexture)
10815                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10816                         else
10817                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10818                         break;
10819                 case TEXTURELAYERTYPE_TEXTURE:
10820                         // singletexture unlit texture with transparency support
10821                         R_Mesh_TexBind(0, layer->texture);
10822                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10823                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10824                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10825                         R_Mesh_TexBind(1, 0);
10826                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10827                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10828                         break;
10829                 case TEXTURELAYERTYPE_FOG:
10830                         // singletexture fogging
10831                         if (layer->texture)
10832                         {
10833                                 R_Mesh_TexBind(0, layer->texture);
10834                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10835                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10836                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10837                         }
10838                         else
10839                         {
10840                                 R_Mesh_TexBind(0, 0);
10841                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10842                         }
10843                         R_Mesh_TexBind(1, 0);
10844                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10845                         // generate a color array for the fog pass
10846                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10847                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10848                         RSurf_DrawBatch();
10849                         break;
10850                 default:
10851                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10852                 }
10853         }
10854         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10855         {
10856                 GL_DepthFunc(GL_LEQUAL);
10857                 GL_AlphaTest(false);
10858         }
10859 }
10860
10861 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10862 {
10863         // OpenGL 1.1 - crusty old voodoo path
10864         qboolean applyfog;
10865         int layerindex;
10866         const texturelayer_t *layer;
10867         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);
10868         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10869
10870         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10871         {
10872                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10873                 {
10874                         if (layerindex == 0)
10875                                 GL_AlphaTest(true);
10876                         else
10877                         {
10878                                 GL_AlphaTest(false);
10879                                 GL_DepthFunc(GL_EQUAL);
10880                         }
10881                 }
10882                 GL_DepthMask(layer->depthmask && writedepth);
10883                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10884                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10885                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10886                 switch (layer->type)
10887                 {
10888                 case TEXTURELAYERTYPE_LITTEXTURE:
10889                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10890                         {
10891                                 // two-pass lit texture with 2x rgbscale
10892                                 // first the lightmap pass
10893                                 R_Mesh_TexBind(0, r_texture_white);
10894                                 R_Mesh_TexMatrix(0, NULL);
10895                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10896                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10897                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10898                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10899                                 else if (FAKELIGHT_ENABLED)
10900                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10901                                 else if (rsurface.uselightmaptexture)
10902                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10903                                 else
10904                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10905                                 // then apply the texture to it
10906                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10907                                 R_Mesh_TexBind(0, layer->texture);
10908                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10909                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10910                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10911                                 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);
10912                         }
10913                         else
10914                         {
10915                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10916                                 R_Mesh_TexBind(0, layer->texture);
10917                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10918                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10919                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10920                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10921                                         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);
10922                                 else if (FAKELIGHT_ENABLED)
10923                                         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);
10924                                 else
10925                                         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);
10926                         }
10927                         break;
10928                 case TEXTURELAYERTYPE_TEXTURE:
10929                         // singletexture unlit texture with transparency support
10930                         R_Mesh_TexBind(0, layer->texture);
10931                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10932                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10933                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10934                         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);
10935                         break;
10936                 case TEXTURELAYERTYPE_FOG:
10937                         // singletexture fogging
10938                         if (layer->texture)
10939                         {
10940                                 R_Mesh_TexBind(0, layer->texture);
10941                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10942                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10943                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10944                         }
10945                         else
10946                         {
10947                                 R_Mesh_TexBind(0, 0);
10948                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10949                         }
10950                         // generate a color array for the fog pass
10951                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10952                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10953                         RSurf_DrawBatch();
10954                         break;
10955                 default:
10956                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10957                 }
10958         }
10959         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10960         {
10961                 GL_DepthFunc(GL_LEQUAL);
10962                 GL_AlphaTest(false);
10963         }
10964 }
10965
10966 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10967 {
10968         int vi;
10969         int j;
10970         r_vertexgeneric_t *batchvertex;
10971         float c[4];
10972
10973 //      R_Mesh_ResetTextureState();
10974         R_SetupShader_Generic_NoTexture(false, false);
10975
10976         if(rsurface.texture && rsurface.texture->currentskinframe)
10977         {
10978                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10979                 c[3] *= rsurface.texture->currentalpha;
10980         }
10981         else
10982         {
10983                 c[0] = 1;
10984                 c[1] = 0;
10985                 c[2] = 1;
10986                 c[3] = 1;
10987         }
10988
10989         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10990         {
10991                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10992                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10993                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10994         }
10995
10996         // brighten it up (as texture value 127 means "unlit")
10997         c[0] *= 2 * r_refdef.view.colorscale;
10998         c[1] *= 2 * r_refdef.view.colorscale;
10999         c[2] *= 2 * r_refdef.view.colorscale;
11000
11001         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11002                 c[3] *= r_wateralpha.value;
11003
11004         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11005         {
11006                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11007                 GL_DepthMask(false);
11008         }
11009         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11010         {
11011                 GL_BlendFunc(GL_ONE, GL_ONE);
11012                 GL_DepthMask(false);
11013         }
11014         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11015         {
11016                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11017                 GL_DepthMask(false);
11018         }
11019         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11020         {
11021                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11022                 GL_DepthMask(false);
11023         }
11024         else
11025         {
11026                 GL_BlendFunc(GL_ONE, GL_ZERO);
11027                 GL_DepthMask(writedepth);
11028         }
11029
11030         if (r_showsurfaces.integer == 3)
11031         {
11032                 rsurface.passcolor4f = NULL;
11033
11034                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11035                 {
11036                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11037
11038                         rsurface.passcolor4f = NULL;
11039                         rsurface.passcolor4f_vertexbuffer = 0;
11040                         rsurface.passcolor4f_bufferoffset = 0;
11041                 }
11042                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11043                 {
11044                         qboolean applycolor = true;
11045                         float one = 1.0;
11046
11047                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11048
11049                         r_refdef.lightmapintensity = 1;
11050                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11051                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11052                 }
11053                 else if (FAKELIGHT_ENABLED)
11054                 {
11055                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11056
11057                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11058                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11059                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11060                 }
11061                 else
11062                 {
11063                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11064
11065                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11066                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11067                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11068                 }
11069
11070                 if(!rsurface.passcolor4f)
11071                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11072
11073                 RSurf_DrawBatch_GL11_ApplyAmbient();
11074                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11075                 if(r_refdef.fogenabled)
11076                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11077                 RSurf_DrawBatch_GL11_ClampColor();
11078
11079                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11080                 R_SetupShader_Generic_NoTexture(false, false);
11081                 RSurf_DrawBatch();
11082         }
11083         else if (!r_refdef.view.showdebug)
11084         {
11085                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11086                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11087                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11088                 {
11089                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11090                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11091                 }
11092                 R_Mesh_PrepareVertices_Generic_Unlock();
11093                 RSurf_DrawBatch();
11094         }
11095         else if (r_showsurfaces.integer == 4)
11096         {
11097                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11098                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11099                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11100                 {
11101                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11102                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11103                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11104                 }
11105                 R_Mesh_PrepareVertices_Generic_Unlock();
11106                 RSurf_DrawBatch();
11107         }
11108         else if (r_showsurfaces.integer == 2)
11109         {
11110                 const int *e;
11111                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11112                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11113                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11114                 {
11115                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11116                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11117                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11118                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11119                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11120                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11121                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11122                 }
11123                 R_Mesh_PrepareVertices_Generic_Unlock();
11124                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11125         }
11126         else
11127         {
11128                 int texturesurfaceindex;
11129                 int k;
11130                 const msurface_t *surface;
11131                 float surfacecolor4f[4];
11132                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11133                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11134                 vi = 0;
11135                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11136                 {
11137                         surface = texturesurfacelist[texturesurfaceindex];
11138                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11139                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11140                         for (j = 0;j < surface->num_vertices;j++)
11141                         {
11142                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11143                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11144                                 vi++;
11145                         }
11146                 }
11147                 R_Mesh_PrepareVertices_Generic_Unlock();
11148                 RSurf_DrawBatch();
11149         }
11150 }
11151
11152 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11153 {
11154         CHECKGLERROR
11155         RSurf_SetupDepthAndCulling();
11156         if (r_showsurfaces.integer)
11157         {
11158                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11159                 return;
11160         }
11161         switch (vid.renderpath)
11162         {
11163         case RENDERPATH_GL20:
11164         case RENDERPATH_D3D9:
11165         case RENDERPATH_D3D10:
11166         case RENDERPATH_D3D11:
11167         case RENDERPATH_SOFT:
11168         case RENDERPATH_GLES2:
11169                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11170                 break;
11171         case RENDERPATH_GL13:
11172         case RENDERPATH_GLES1:
11173                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11174                 break;
11175         case RENDERPATH_GL11:
11176                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11177                 break;
11178         }
11179         CHECKGLERROR
11180 }
11181
11182 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11183 {
11184         CHECKGLERROR
11185         RSurf_SetupDepthAndCulling();
11186         if (r_showsurfaces.integer)
11187         {
11188                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11189                 return;
11190         }
11191         switch (vid.renderpath)
11192         {
11193         case RENDERPATH_GL20:
11194         case RENDERPATH_D3D9:
11195         case RENDERPATH_D3D10:
11196         case RENDERPATH_D3D11:
11197         case RENDERPATH_SOFT:
11198         case RENDERPATH_GLES2:
11199                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11200                 break;
11201         case RENDERPATH_GL13:
11202         case RENDERPATH_GLES1:
11203                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11204                 break;
11205         case RENDERPATH_GL11:
11206                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11207                 break;
11208         }
11209         CHECKGLERROR
11210 }
11211
11212 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11213 {
11214         int i, j;
11215         int texturenumsurfaces, endsurface;
11216         texture_t *texture;
11217         const msurface_t *surface;
11218         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11219
11220         // if the model is static it doesn't matter what value we give for
11221         // wantnormals and wanttangents, so this logic uses only rules applicable
11222         // to a model, knowing that they are meaningless otherwise
11223         if (ent == r_refdef.scene.worldentity)
11224                 RSurf_ActiveWorldEntity();
11225         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11226                 RSurf_ActiveModelEntity(ent, false, false, false);
11227         else
11228         {
11229                 switch (vid.renderpath)
11230                 {
11231                 case RENDERPATH_GL20:
11232                 case RENDERPATH_D3D9:
11233                 case RENDERPATH_D3D10:
11234                 case RENDERPATH_D3D11:
11235                 case RENDERPATH_SOFT:
11236                 case RENDERPATH_GLES2:
11237                         RSurf_ActiveModelEntity(ent, true, true, false);
11238                         break;
11239                 case RENDERPATH_GL11:
11240                 case RENDERPATH_GL13:
11241                 case RENDERPATH_GLES1:
11242                         RSurf_ActiveModelEntity(ent, true, false, false);
11243                         break;
11244                 }
11245         }
11246
11247         if (r_transparentdepthmasking.integer)
11248         {
11249                 qboolean setup = false;
11250                 for (i = 0;i < numsurfaces;i = j)
11251                 {
11252                         j = i + 1;
11253                         surface = rsurface.modelsurfaces + surfacelist[i];
11254                         texture = surface->texture;
11255                         rsurface.texture = R_GetCurrentTexture(texture);
11256                         rsurface.lightmaptexture = NULL;
11257                         rsurface.deluxemaptexture = NULL;
11258                         rsurface.uselightmaptexture = false;
11259                         // scan ahead until we find a different texture
11260                         endsurface = min(i + 1024, numsurfaces);
11261                         texturenumsurfaces = 0;
11262                         texturesurfacelist[texturenumsurfaces++] = surface;
11263                         for (;j < endsurface;j++)
11264                         {
11265                                 surface = rsurface.modelsurfaces + surfacelist[j];
11266                                 if (texture != surface->texture)
11267                                         break;
11268                                 texturesurfacelist[texturenumsurfaces++] = surface;
11269                         }
11270                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11271                                 continue;
11272                         // render the range of surfaces as depth
11273                         if (!setup)
11274                         {
11275                                 setup = true;
11276                                 GL_ColorMask(0,0,0,0);
11277                                 GL_Color(1,1,1,1);
11278                                 GL_DepthTest(true);
11279                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11280                                 GL_DepthMask(true);
11281 //                              R_Mesh_ResetTextureState();
11282                         }
11283                         RSurf_SetupDepthAndCulling();
11284                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11285                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11286                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11287                         RSurf_DrawBatch();
11288                 }
11289                 if (setup)
11290                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11291         }
11292
11293         for (i = 0;i < numsurfaces;i = j)
11294         {
11295                 j = i + 1;
11296                 surface = rsurface.modelsurfaces + surfacelist[i];
11297                 texture = surface->texture;
11298                 rsurface.texture = R_GetCurrentTexture(texture);
11299                 // scan ahead until we find a different texture
11300                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11301                 texturenumsurfaces = 0;
11302                 texturesurfacelist[texturenumsurfaces++] = surface;
11303                 if(FAKELIGHT_ENABLED)
11304                 {
11305                         rsurface.lightmaptexture = NULL;
11306                         rsurface.deluxemaptexture = NULL;
11307                         rsurface.uselightmaptexture = false;
11308                         for (;j < endsurface;j++)
11309                         {
11310                                 surface = rsurface.modelsurfaces + surfacelist[j];
11311                                 if (texture != surface->texture)
11312                                         break;
11313                                 texturesurfacelist[texturenumsurfaces++] = surface;
11314                         }
11315                 }
11316                 else
11317                 {
11318                         rsurface.lightmaptexture = surface->lightmaptexture;
11319                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11320                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11321                         for (;j < endsurface;j++)
11322                         {
11323                                 surface = rsurface.modelsurfaces + surfacelist[j];
11324                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11325                                         break;
11326                                 texturesurfacelist[texturenumsurfaces++] = surface;
11327                         }
11328                 }
11329                 // render the range of surfaces
11330                 if (ent == r_refdef.scene.worldentity)
11331                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11332                 else
11333                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11334         }
11335         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11336 }
11337
11338 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11339 {
11340         // transparent surfaces get pushed off into the transparent queue
11341         int surfacelistindex;
11342         const msurface_t *surface;
11343         vec3_t tempcenter, center;
11344         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11345         {
11346                 surface = texturesurfacelist[surfacelistindex];
11347                 if (r_transparent_sortsurfacesbynearest.integer)
11348                 {
11349                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11350                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11351                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11352                 }
11353                 else
11354                 {
11355                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11356                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11357                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11358                 }
11359                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11360                 if (rsurface.entity->transparent_offset) // transparent offset
11361                 {
11362                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11363                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11364                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11365                 }
11366                 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);
11367         }
11368 }
11369
11370 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11371 {
11372         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11373                 return;
11374         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11375                 return;
11376         RSurf_SetupDepthAndCulling();
11377         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11378         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11379         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11380         RSurf_DrawBatch();
11381 }
11382
11383 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11384 {
11385         CHECKGLERROR
11386         if (depthonly)
11387                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11388         else if (prepass)
11389         {
11390                 if (!rsurface.texture->currentnumlayers)
11391                         return;
11392                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11393                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11394                 else
11395                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11396         }
11397         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11398                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11399         else if (!rsurface.texture->currentnumlayers)
11400                 return;
11401         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11402         {
11403                 // in the deferred case, transparent surfaces were queued during prepass
11404                 if (!r_shadow_usingdeferredprepass)
11405                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11406         }
11407         else
11408         {
11409                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11410                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11411         }
11412         CHECKGLERROR
11413 }
11414
11415 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11416 {
11417         int i, j;
11418         texture_t *texture;
11419         R_FrameData_SetMark();
11420         // break the surface list down into batches by texture and use of lightmapping
11421         for (i = 0;i < numsurfaces;i = j)
11422         {
11423                 j = i + 1;
11424                 // texture is the base texture pointer, rsurface.texture is the
11425                 // current frame/skin the texture is directing us to use (for example
11426                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11427                 // use skin 1 instead)
11428                 texture = surfacelist[i]->texture;
11429                 rsurface.texture = R_GetCurrentTexture(texture);
11430                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11431                 {
11432                         // if this texture is not the kind we want, skip ahead to the next one
11433                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11434                                 ;
11435                         continue;
11436                 }
11437                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11438                 {
11439                         rsurface.lightmaptexture = NULL;
11440                         rsurface.deluxemaptexture = NULL;
11441                         rsurface.uselightmaptexture = false;
11442                         // simply scan ahead until we find a different texture or lightmap state
11443                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11444                                 ;
11445                 }
11446                 else
11447                 {
11448                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11449                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11450                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11451                         // simply scan ahead until we find a different texture or lightmap state
11452                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11453                                 ;
11454                 }
11455                 // render the range of surfaces
11456                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11457         }
11458         R_FrameData_ReturnToMark();
11459 }
11460
11461 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11462 {
11463         CHECKGLERROR
11464         if (depthonly)
11465                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11466         else if (prepass)
11467         {
11468                 if (!rsurface.texture->currentnumlayers)
11469                         return;
11470                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11471                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11472                 else
11473                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11474         }
11475         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11476                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11477         else if (!rsurface.texture->currentnumlayers)
11478                 return;
11479         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11480         {
11481                 // in the deferred case, transparent surfaces were queued during prepass
11482                 if (!r_shadow_usingdeferredprepass)
11483                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11484         }
11485         else
11486         {
11487                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11488                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11489         }
11490         CHECKGLERROR
11491 }
11492
11493 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11494 {
11495         int i, j;
11496         texture_t *texture;
11497         R_FrameData_SetMark();
11498         // break the surface list down into batches by texture and use of lightmapping
11499         for (i = 0;i < numsurfaces;i = j)
11500         {
11501                 j = i + 1;
11502                 // texture is the base texture pointer, rsurface.texture is the
11503                 // current frame/skin the texture is directing us to use (for example
11504                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11505                 // use skin 1 instead)
11506                 texture = surfacelist[i]->texture;
11507                 rsurface.texture = R_GetCurrentTexture(texture);
11508                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11509                 {
11510                         // if this texture is not the kind we want, skip ahead to the next one
11511                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11512                                 ;
11513                         continue;
11514                 }
11515                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11516                 {
11517                         rsurface.lightmaptexture = NULL;
11518                         rsurface.deluxemaptexture = NULL;
11519                         rsurface.uselightmaptexture = false;
11520                         // simply scan ahead until we find a different texture or lightmap state
11521                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11522                                 ;
11523                 }
11524                 else
11525                 {
11526                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11527                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11528                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11529                         // simply scan ahead until we find a different texture or lightmap state
11530                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11531                                 ;
11532                 }
11533                 // render the range of surfaces
11534                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11535         }
11536         R_FrameData_ReturnToMark();
11537 }
11538
11539 float locboxvertex3f[6*4*3] =
11540 {
11541         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11542         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11543         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11544         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11545         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11546         1,0,0, 0,0,0, 0,1,0, 1,1,0
11547 };
11548
11549 unsigned short locboxelements[6*2*3] =
11550 {
11551          0, 1, 2, 0, 2, 3,
11552          4, 5, 6, 4, 6, 7,
11553          8, 9,10, 8,10,11,
11554         12,13,14, 12,14,15,
11555         16,17,18, 16,18,19,
11556         20,21,22, 20,22,23
11557 };
11558
11559 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11560 {
11561         int i, j;
11562         cl_locnode_t *loc = (cl_locnode_t *)ent;
11563         vec3_t mins, size;
11564         float vertex3f[6*4*3];
11565         CHECKGLERROR
11566         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11567         GL_DepthMask(false);
11568         GL_DepthRange(0, 1);
11569         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11570         GL_DepthTest(true);
11571         GL_CullFace(GL_NONE);
11572         R_EntityMatrix(&identitymatrix);
11573
11574 //      R_Mesh_ResetTextureState();
11575
11576         i = surfacelist[0];
11577         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11578                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11579                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11580                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11581
11582         if (VectorCompare(loc->mins, loc->maxs))
11583         {
11584                 VectorSet(size, 2, 2, 2);
11585                 VectorMA(loc->mins, -0.5f, size, mins);
11586         }
11587         else
11588         {
11589                 VectorCopy(loc->mins, mins);
11590                 VectorSubtract(loc->maxs, loc->mins, size);
11591         }
11592
11593         for (i = 0;i < 6*4*3;)
11594                 for (j = 0;j < 3;j++, i++)
11595                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11596
11597         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11598         R_SetupShader_Generic_NoTexture(false, false);
11599         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11600 }
11601
11602 void R_DrawLocs(void)
11603 {
11604         int index;
11605         cl_locnode_t *loc, *nearestloc;
11606         vec3_t center;
11607         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11608         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11609         {
11610                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11611                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11612         }
11613 }
11614
11615 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11616 {
11617         if (decalsystem->decals)
11618                 Mem_Free(decalsystem->decals);
11619         memset(decalsystem, 0, sizeof(*decalsystem));
11620 }
11621
11622 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)
11623 {
11624         tridecal_t *decal;
11625         tridecal_t *decals;
11626         int i;
11627
11628         // expand or initialize the system
11629         if (decalsystem->maxdecals <= decalsystem->numdecals)
11630         {
11631                 decalsystem_t old = *decalsystem;
11632                 qboolean useshortelements;
11633                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11634                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11635                 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)));
11636                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11637                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11638                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11639                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11640                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11641                 if (decalsystem->numdecals)
11642                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11643                 if (old.decals)
11644                         Mem_Free(old.decals);
11645                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11646                         decalsystem->element3i[i] = i;
11647                 if (useshortelements)
11648                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11649                                 decalsystem->element3s[i] = i;
11650         }
11651
11652         // grab a decal and search for another free slot for the next one
11653         decals = decalsystem->decals;
11654         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11655         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11656                 ;
11657         decalsystem->freedecal = i;
11658         if (decalsystem->numdecals <= i)
11659                 decalsystem->numdecals = i + 1;
11660
11661         // initialize the decal
11662         decal->lived = 0;
11663         decal->triangleindex = triangleindex;
11664         decal->surfaceindex = surfaceindex;
11665         decal->decalsequence = decalsequence;
11666         decal->color4f[0][0] = c0[0];
11667         decal->color4f[0][1] = c0[1];
11668         decal->color4f[0][2] = c0[2];
11669         decal->color4f[0][3] = 1;
11670         decal->color4f[1][0] = c1[0];
11671         decal->color4f[1][1] = c1[1];
11672         decal->color4f[1][2] = c1[2];
11673         decal->color4f[1][3] = 1;
11674         decal->color4f[2][0] = c2[0];
11675         decal->color4f[2][1] = c2[1];
11676         decal->color4f[2][2] = c2[2];
11677         decal->color4f[2][3] = 1;
11678         decal->vertex3f[0][0] = v0[0];
11679         decal->vertex3f[0][1] = v0[1];
11680         decal->vertex3f[0][2] = v0[2];
11681         decal->vertex3f[1][0] = v1[0];
11682         decal->vertex3f[1][1] = v1[1];
11683         decal->vertex3f[1][2] = v1[2];
11684         decal->vertex3f[2][0] = v2[0];
11685         decal->vertex3f[2][1] = v2[1];
11686         decal->vertex3f[2][2] = v2[2];
11687         decal->texcoord2f[0][0] = t0[0];
11688         decal->texcoord2f[0][1] = t0[1];
11689         decal->texcoord2f[1][0] = t1[0];
11690         decal->texcoord2f[1][1] = t1[1];
11691         decal->texcoord2f[2][0] = t2[0];
11692         decal->texcoord2f[2][1] = t2[1];
11693         TriangleNormal(v0, v1, v2, decal->plane);
11694         VectorNormalize(decal->plane);
11695         decal->plane[3] = DotProduct(v0, decal->plane);
11696 }
11697
11698 extern cvar_t cl_decals_bias;
11699 extern cvar_t cl_decals_models;
11700 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11701 // baseparms, parms, temps
11702 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)
11703 {
11704         int cornerindex;
11705         int index;
11706         float v[9][3];
11707         const float *vertex3f;
11708         const float *normal3f;
11709         int numpoints;
11710         float points[2][9][3];
11711         float temp[3];
11712         float tc[9][2];
11713         float f;
11714         float c[9][4];
11715         const int *e;
11716
11717         e = rsurface.modelelement3i + 3*triangleindex;
11718
11719         vertex3f = rsurface.modelvertex3f;
11720         normal3f = rsurface.modelnormal3f;
11721
11722         if (normal3f)
11723         {
11724                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11725                 {
11726                         index = 3*e[cornerindex];
11727                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11728                 }
11729         }
11730         else
11731         {
11732                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11733                 {
11734                         index = 3*e[cornerindex];
11735                         VectorCopy(vertex3f + index, v[cornerindex]);
11736                 }
11737         }
11738
11739         // cull backfaces
11740         //TriangleNormal(v[0], v[1], v[2], normal);
11741         //if (DotProduct(normal, localnormal) < 0.0f)
11742         //      continue;
11743         // clip by each of the box planes formed from the projection matrix
11744         // if anything survives, we emit the decal
11745         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]);
11746         if (numpoints < 3)
11747                 return;
11748         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]);
11749         if (numpoints < 3)
11750                 return;
11751         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]);
11752         if (numpoints < 3)
11753                 return;
11754         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]);
11755         if (numpoints < 3)
11756                 return;
11757         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]);
11758         if (numpoints < 3)
11759                 return;
11760         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]);
11761         if (numpoints < 3)
11762                 return;
11763         // some part of the triangle survived, so we have to accept it...
11764         if (dynamic)
11765         {
11766                 // dynamic always uses the original triangle
11767                 numpoints = 3;
11768                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11769                 {
11770                         index = 3*e[cornerindex];
11771                         VectorCopy(vertex3f + index, v[cornerindex]);
11772                 }
11773         }
11774         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11775         {
11776                 // convert vertex positions to texcoords
11777                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11778                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11779                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11780                 // calculate distance fade from the projection origin
11781                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11782                 f = bound(0.0f, f, 1.0f);
11783                 c[cornerindex][0] = r * f;
11784                 c[cornerindex][1] = g * f;
11785                 c[cornerindex][2] = b * f;
11786                 c[cornerindex][3] = 1.0f;
11787                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11788         }
11789         if (dynamic)
11790                 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);
11791         else
11792                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11793                         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);
11794 }
11795 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)
11796 {
11797         matrix4x4_t projection;
11798         decalsystem_t *decalsystem;
11799         qboolean dynamic;
11800         dp_model_t *model;
11801         const msurface_t *surface;
11802         const msurface_t *surfaces;
11803         const int *surfacelist;
11804         const texture_t *texture;
11805         int numtriangles;
11806         int numsurfacelist;
11807         int surfacelistindex;
11808         int surfaceindex;
11809         int triangleindex;
11810         float localorigin[3];
11811         float localnormal[3];
11812         float localmins[3];
11813         float localmaxs[3];
11814         float localsize;
11815         //float normal[3];
11816         float planes[6][4];
11817         float angles[3];
11818         bih_t *bih;
11819         int bih_triangles_count;
11820         int bih_triangles[256];
11821         int bih_surfaces[256];
11822
11823         decalsystem = &ent->decalsystem;
11824         model = ent->model;
11825         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11826         {
11827                 R_DecalSystem_Reset(&ent->decalsystem);
11828                 return;
11829         }
11830
11831         if (!model->brush.data_leafs && !cl_decals_models.integer)
11832         {
11833                 if (decalsystem->model)
11834                         R_DecalSystem_Reset(decalsystem);
11835                 return;
11836         }
11837
11838         if (decalsystem->model != model)
11839                 R_DecalSystem_Reset(decalsystem);
11840         decalsystem->model = model;
11841
11842         RSurf_ActiveModelEntity(ent, true, false, false);
11843
11844         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11845         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11846         VectorNormalize(localnormal);
11847         localsize = worldsize*rsurface.inversematrixscale;
11848         localmins[0] = localorigin[0] - localsize;
11849         localmins[1] = localorigin[1] - localsize;
11850         localmins[2] = localorigin[2] - localsize;
11851         localmaxs[0] = localorigin[0] + localsize;
11852         localmaxs[1] = localorigin[1] + localsize;
11853         localmaxs[2] = localorigin[2] + localsize;
11854
11855         //VectorCopy(localnormal, planes[4]);
11856         //VectorVectors(planes[4], planes[2], planes[0]);
11857         AnglesFromVectors(angles, localnormal, NULL, false);
11858         AngleVectors(angles, planes[0], planes[2], planes[4]);
11859         VectorNegate(planes[0], planes[1]);
11860         VectorNegate(planes[2], planes[3]);
11861         VectorNegate(planes[4], planes[5]);
11862         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11863         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11864         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11865         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11866         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11867         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11868
11869 #if 1
11870 // works
11871 {
11872         matrix4x4_t forwardprojection;
11873         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11874         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11875 }
11876 #else
11877 // broken
11878 {
11879         float projectionvector[4][3];
11880         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11881         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11882         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11883         projectionvector[0][0] = planes[0][0] * ilocalsize;
11884         projectionvector[0][1] = planes[1][0] * ilocalsize;
11885         projectionvector[0][2] = planes[2][0] * ilocalsize;
11886         projectionvector[1][0] = planes[0][1] * ilocalsize;
11887         projectionvector[1][1] = planes[1][1] * ilocalsize;
11888         projectionvector[1][2] = planes[2][1] * ilocalsize;
11889         projectionvector[2][0] = planes[0][2] * ilocalsize;
11890         projectionvector[2][1] = planes[1][2] * ilocalsize;
11891         projectionvector[2][2] = planes[2][2] * ilocalsize;
11892         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11893         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11894         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11895         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11896 }
11897 #endif
11898
11899         dynamic = model->surfmesh.isanimated;
11900         numsurfacelist = model->nummodelsurfaces;
11901         surfacelist = model->sortedmodelsurfaces;
11902         surfaces = model->data_surfaces;
11903
11904         bih = NULL;
11905         bih_triangles_count = -1;
11906         if(!dynamic)
11907         {
11908                 if(model->render_bih.numleafs)
11909                         bih = &model->render_bih;
11910                 else if(model->collision_bih.numleafs)
11911                         bih = &model->collision_bih;
11912         }
11913         if(bih)
11914                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11915         if(bih_triangles_count == 0)
11916                 return;
11917         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11918                 return;
11919         if(bih_triangles_count > 0)
11920         {
11921                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11922                 {
11923                         surfaceindex = bih_surfaces[triangleindex];
11924                         surface = surfaces + surfaceindex;
11925                         texture = surface->texture;
11926                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11927                                 continue;
11928                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11929                                 continue;
11930                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11931                 }
11932         }
11933         else
11934         {
11935                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11936                 {
11937                         surfaceindex = surfacelist[surfacelistindex];
11938                         surface = surfaces + surfaceindex;
11939                         // check cull box first because it rejects more than any other check
11940                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11941                                 continue;
11942                         // skip transparent surfaces
11943                         texture = surface->texture;
11944                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11945                                 continue;
11946                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11947                                 continue;
11948                         numtriangles = surface->num_triangles;
11949                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11950                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11951                 }
11952         }
11953 }
11954
11955 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11956 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)
11957 {
11958         int renderentityindex;
11959         float worldmins[3];
11960         float worldmaxs[3];
11961         entity_render_t *ent;
11962
11963         if (!cl_decals_newsystem.integer)
11964                 return;
11965
11966         worldmins[0] = worldorigin[0] - worldsize;
11967         worldmins[1] = worldorigin[1] - worldsize;
11968         worldmins[2] = worldorigin[2] - worldsize;
11969         worldmaxs[0] = worldorigin[0] + worldsize;
11970         worldmaxs[1] = worldorigin[1] + worldsize;
11971         worldmaxs[2] = worldorigin[2] + worldsize;
11972
11973         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11974
11975         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11976         {
11977                 ent = r_refdef.scene.entities[renderentityindex];
11978                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11979                         continue;
11980
11981                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11982         }
11983 }
11984
11985 typedef struct r_decalsystem_splatqueue_s
11986 {
11987         vec3_t worldorigin;
11988         vec3_t worldnormal;
11989         float color[4];
11990         float tcrange[4];
11991         float worldsize;
11992         int decalsequence;
11993 }
11994 r_decalsystem_splatqueue_t;
11995
11996 int r_decalsystem_numqueued = 0;
11997 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11998
11999 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)
12000 {
12001         r_decalsystem_splatqueue_t *queue;
12002
12003         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12004                 return;
12005
12006         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12007         VectorCopy(worldorigin, queue->worldorigin);
12008         VectorCopy(worldnormal, queue->worldnormal);
12009         Vector4Set(queue->color, r, g, b, a);
12010         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12011         queue->worldsize = worldsize;
12012         queue->decalsequence = cl.decalsequence++;
12013 }
12014
12015 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12016 {
12017         int i;
12018         r_decalsystem_splatqueue_t *queue;
12019
12020         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12021                 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);
12022         r_decalsystem_numqueued = 0;
12023 }
12024
12025 extern cvar_t cl_decals_max;
12026 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12027 {
12028         int i;
12029         decalsystem_t *decalsystem = &ent->decalsystem;
12030         int numdecals;
12031         int killsequence;
12032         tridecal_t *decal;
12033         float frametime;
12034         float lifetime;
12035
12036         if (!decalsystem->numdecals)
12037                 return;
12038
12039         if (r_showsurfaces.integer)
12040                 return;
12041
12042         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12043         {
12044                 R_DecalSystem_Reset(decalsystem);
12045                 return;
12046         }
12047
12048         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12049         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12050
12051         if (decalsystem->lastupdatetime)
12052                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12053         else
12054                 frametime = 0;
12055         decalsystem->lastupdatetime = r_refdef.scene.time;
12056         numdecals = decalsystem->numdecals;
12057
12058         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12059         {
12060                 if (decal->color4f[0][3])
12061                 {
12062                         decal->lived += frametime;
12063                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12064                         {
12065                                 memset(decal, 0, sizeof(*decal));
12066                                 if (decalsystem->freedecal > i)
12067                                         decalsystem->freedecal = i;
12068                         }
12069                 }
12070         }
12071         decal = decalsystem->decals;
12072         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12073                 numdecals--;
12074
12075         // collapse the array by shuffling the tail decals into the gaps
12076         for (;;)
12077         {
12078                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12079                         decalsystem->freedecal++;
12080                 if (decalsystem->freedecal == numdecals)
12081                         break;
12082                 decal[decalsystem->freedecal] = decal[--numdecals];
12083         }
12084
12085         decalsystem->numdecals = numdecals;
12086
12087         if (numdecals <= 0)
12088         {
12089                 // if there are no decals left, reset decalsystem
12090                 R_DecalSystem_Reset(decalsystem);
12091         }
12092 }
12093
12094 extern skinframe_t *decalskinframe;
12095 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12096 {
12097         int i;
12098         decalsystem_t *decalsystem = &ent->decalsystem;
12099         int numdecals;
12100         tridecal_t *decal;
12101         float faderate;
12102         float alpha;
12103         float *v3f;
12104         float *c4f;
12105         float *t2f;
12106         const int *e;
12107         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12108         int numtris = 0;
12109
12110         numdecals = decalsystem->numdecals;
12111         if (!numdecals)
12112                 return;
12113
12114         if (r_showsurfaces.integer)
12115                 return;
12116
12117         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12118         {
12119                 R_DecalSystem_Reset(decalsystem);
12120                 return;
12121         }
12122
12123         // if the model is static it doesn't matter what value we give for
12124         // wantnormals and wanttangents, so this logic uses only rules applicable
12125         // to a model, knowing that they are meaningless otherwise
12126         if (ent == r_refdef.scene.worldentity)
12127                 RSurf_ActiveWorldEntity();
12128         else
12129                 RSurf_ActiveModelEntity(ent, false, false, false);
12130
12131         decalsystem->lastupdatetime = r_refdef.scene.time;
12132
12133         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12134
12135         // update vertex positions for animated models
12136         v3f = decalsystem->vertex3f;
12137         c4f = decalsystem->color4f;
12138         t2f = decalsystem->texcoord2f;
12139         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12140         {
12141                 if (!decal->color4f[0][3])
12142                         continue;
12143
12144                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12145                         continue;
12146
12147                 // skip backfaces
12148                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12149                         continue;
12150
12151                 // update color values for fading decals
12152                 if (decal->lived >= cl_decals_time.value)
12153                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12154                 else
12155                         alpha = 1.0f;
12156
12157                 c4f[ 0] = decal->color4f[0][0] * alpha;
12158                 c4f[ 1] = decal->color4f[0][1] * alpha;
12159                 c4f[ 2] = decal->color4f[0][2] * alpha;
12160                 c4f[ 3] = 1;
12161                 c4f[ 4] = decal->color4f[1][0] * alpha;
12162                 c4f[ 5] = decal->color4f[1][1] * alpha;
12163                 c4f[ 6] = decal->color4f[1][2] * alpha;
12164                 c4f[ 7] = 1;
12165                 c4f[ 8] = decal->color4f[2][0] * alpha;
12166                 c4f[ 9] = decal->color4f[2][1] * alpha;
12167                 c4f[10] = decal->color4f[2][2] * alpha;
12168                 c4f[11] = 1;
12169
12170                 t2f[0] = decal->texcoord2f[0][0];
12171                 t2f[1] = decal->texcoord2f[0][1];
12172                 t2f[2] = decal->texcoord2f[1][0];
12173                 t2f[3] = decal->texcoord2f[1][1];
12174                 t2f[4] = decal->texcoord2f[2][0];
12175                 t2f[5] = decal->texcoord2f[2][1];
12176
12177                 // update vertex positions for animated models
12178                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12179                 {
12180                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12181                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12182                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12183                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12184                 }
12185                 else
12186                 {
12187                         VectorCopy(decal->vertex3f[0], v3f);
12188                         VectorCopy(decal->vertex3f[1], v3f + 3);
12189                         VectorCopy(decal->vertex3f[2], v3f + 6);
12190                 }
12191
12192                 if (r_refdef.fogenabled)
12193                 {
12194                         alpha = RSurf_FogVertex(v3f);
12195                         VectorScale(c4f, alpha, c4f);
12196                         alpha = RSurf_FogVertex(v3f + 3);
12197                         VectorScale(c4f + 4, alpha, c4f + 4);
12198                         alpha = RSurf_FogVertex(v3f + 6);
12199                         VectorScale(c4f + 8, alpha, c4f + 8);
12200                 }
12201
12202                 v3f += 9;
12203                 c4f += 12;
12204                 t2f += 6;
12205                 numtris++;
12206         }
12207
12208         if (numtris > 0)
12209         {
12210                 r_refdef.stats[r_stat_drawndecals] += numtris;
12211
12212                 // now render the decals all at once
12213                 // (this assumes they all use one particle font texture!)
12214                 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);
12215 //              R_Mesh_ResetTextureState();
12216                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12217                 GL_DepthMask(false);
12218                 GL_DepthRange(0, 1);
12219                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12220                 GL_DepthTest(true);
12221                 GL_CullFace(GL_NONE);
12222                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12223                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12224                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12225         }
12226 }
12227
12228 static void R_DrawModelDecals(void)
12229 {
12230         int i, numdecals;
12231
12232         // fade faster when there are too many decals
12233         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12234         for (i = 0;i < r_refdef.scene.numentities;i++)
12235                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12236
12237         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12238         for (i = 0;i < r_refdef.scene.numentities;i++)
12239                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12240                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12241
12242         R_DecalSystem_ApplySplatEntitiesQueue();
12243
12244         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12245         for (i = 0;i < r_refdef.scene.numentities;i++)
12246                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12247
12248         r_refdef.stats[r_stat_totaldecals] += numdecals;
12249
12250         if (r_showsurfaces.integer)
12251                 return;
12252
12253         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12254
12255         for (i = 0;i < r_refdef.scene.numentities;i++)
12256         {
12257                 if (!r_refdef.viewcache.entityvisible[i])
12258                         continue;
12259                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12260                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12261         }
12262 }
12263
12264 extern cvar_t mod_collision_bih;
12265 static void R_DrawDebugModel(void)
12266 {
12267         entity_render_t *ent = rsurface.entity;
12268         int i, j, flagsmask;
12269         const msurface_t *surface;
12270         dp_model_t *model = ent->model;
12271
12272         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12273                 return;
12274
12275         if (r_showoverdraw.value > 0)
12276         {
12277                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12278                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12279                 R_SetupShader_Generic_NoTexture(false, false);
12280                 GL_DepthTest(false);
12281                 GL_DepthMask(false);
12282                 GL_DepthRange(0, 1);
12283                 GL_BlendFunc(GL_ONE, GL_ONE);
12284                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12285                 {
12286                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12287                                 continue;
12288                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12289                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12290                         {
12291                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12292                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12293                                 if (!rsurface.texture->currentlayers->depthmask)
12294                                         GL_Color(c, 0, 0, 1.0f);
12295                                 else if (ent == r_refdef.scene.worldentity)
12296                                         GL_Color(c, c, c, 1.0f);
12297                                 else
12298                                         GL_Color(0, c, 0, 1.0f);
12299                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12300                                 RSurf_DrawBatch();
12301                         }
12302                 }
12303                 rsurface.texture = NULL;
12304         }
12305
12306         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12307
12308 //      R_Mesh_ResetTextureState();
12309         R_SetupShader_Generic_NoTexture(false, false);
12310         GL_DepthRange(0, 1);
12311         GL_DepthTest(!r_showdisabledepthtest.integer);
12312         GL_DepthMask(false);
12313         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12314
12315         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12316         {
12317                 int triangleindex;
12318                 int bihleafindex;
12319                 qboolean cullbox = false;
12320                 const q3mbrush_t *brush;
12321                 const bih_t *bih = &model->collision_bih;
12322                 const bih_leaf_t *bihleaf;
12323                 float vertex3f[3][3];
12324                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12325                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12326                 {
12327                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12328                                 continue;
12329                         switch (bihleaf->type)
12330                         {
12331                         case BIH_BRUSH:
12332                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12333                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12334                                 {
12335                                         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);
12336                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12337                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12338                                 }
12339                                 break;
12340                         case BIH_COLLISIONTRIANGLE:
12341                                 triangleindex = bihleaf->itemindex;
12342                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12343                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12344                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12345                                 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);
12346                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12347                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12348                                 break;
12349                         case BIH_RENDERTRIANGLE:
12350                                 triangleindex = bihleaf->itemindex;
12351                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12352                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12353                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12354                                 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);
12355                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12356                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12357                                 break;
12358                         }
12359                 }
12360         }
12361
12362         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12363
12364 #ifndef USE_GLES2
12365         if (r_showtris.integer && qglPolygonMode)
12366         {
12367                 if (r_showdisabledepthtest.integer)
12368                 {
12369                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12370                         GL_DepthMask(false);
12371                 }
12372                 else
12373                 {
12374                         GL_BlendFunc(GL_ONE, GL_ZERO);
12375                         GL_DepthMask(true);
12376                 }
12377                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12378                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12379                 {
12380                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12381                                 continue;
12382                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12383                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12384                         {
12385                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12386                                 if (!rsurface.texture->currentlayers->depthmask)
12387                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12388                                 else if (ent == r_refdef.scene.worldentity)
12389                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12390                                 else
12391                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12392                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12393                                 RSurf_DrawBatch();
12394                         }
12395                 }
12396                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12397                 rsurface.texture = NULL;
12398         }
12399
12400         if (r_shownormals.value != 0 && qglBegin)
12401         {
12402                 int l, k;
12403                 vec3_t v;
12404                 if (r_showdisabledepthtest.integer)
12405                 {
12406                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12407                         GL_DepthMask(false);
12408                 }
12409                 else
12410                 {
12411                         GL_BlendFunc(GL_ONE, GL_ZERO);
12412                         GL_DepthMask(true);
12413                 }
12414                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12415                 {
12416                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12417                                 continue;
12418                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12419                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12420                         {
12421                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12422                                 qglBegin(GL_LINES);
12423                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12424                                 {
12425                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12426                                         {
12427                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12428                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12429                                                 qglVertex3f(v[0], v[1], v[2]);
12430                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12431                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12432                                                 qglVertex3f(v[0], v[1], v[2]);
12433                                         }
12434                                 }
12435                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12436                                 {
12437                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12438                                         {
12439                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12440                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12441                                                 qglVertex3f(v[0], v[1], v[2]);
12442                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12443                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12444                                                 qglVertex3f(v[0], v[1], v[2]);
12445                                         }
12446                                 }
12447                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12448                                 {
12449                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12450                                         {
12451                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12452                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12453                                                 qglVertex3f(v[0], v[1], v[2]);
12454                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12455                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12456                                                 qglVertex3f(v[0], v[1], v[2]);
12457                                         }
12458                                 }
12459                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12460                                 {
12461                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12462                                         {
12463                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12464                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12465                                                 qglVertex3f(v[0], v[1], v[2]);
12466                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12467                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12468                                                 qglVertex3f(v[0], v[1], v[2]);
12469                                         }
12470                                 }
12471                                 qglEnd();
12472                                 CHECKGLERROR
12473                         }
12474                 }
12475                 rsurface.texture = NULL;
12476         }
12477 #endif
12478 }
12479
12480 int r_maxsurfacelist = 0;
12481 const msurface_t **r_surfacelist = NULL;
12482 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12483 {
12484         int i, j, endj, flagsmask;
12485         dp_model_t *model = r_refdef.scene.worldmodel;
12486         msurface_t *surfaces;
12487         unsigned char *update;
12488         int numsurfacelist = 0;
12489         if (model == NULL)
12490                 return;
12491
12492         if (r_maxsurfacelist < model->num_surfaces)
12493         {
12494                 r_maxsurfacelist = model->num_surfaces;
12495                 if (r_surfacelist)
12496                         Mem_Free((msurface_t**)r_surfacelist);
12497                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12498         }
12499
12500         RSurf_ActiveWorldEntity();
12501
12502         surfaces = model->data_surfaces;
12503         update = model->brushq1.lightmapupdateflags;
12504
12505         // update light styles on this submodel
12506         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12507         {
12508                 model_brush_lightstyleinfo_t *style;
12509                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12510                 {
12511                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12512                         {
12513                                 int *list = style->surfacelist;
12514                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12515                                 for (j = 0;j < style->numsurfaces;j++)
12516                                         update[list[j]] = true;
12517                         }
12518                 }
12519         }
12520
12521         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12522
12523         if (debug)
12524         {
12525                 R_DrawDebugModel();
12526                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12527                 return;
12528         }
12529
12530         rsurface.lightmaptexture = NULL;
12531         rsurface.deluxemaptexture = NULL;
12532         rsurface.uselightmaptexture = false;
12533         rsurface.texture = NULL;
12534         rsurface.rtlight = NULL;
12535         numsurfacelist = 0;
12536         // add visible surfaces to draw list
12537         for (i = 0;i < model->nummodelsurfaces;i++)
12538         {
12539                 j = model->sortedmodelsurfaces[i];
12540                 if (r_refdef.viewcache.world_surfacevisible[j])
12541                         r_surfacelist[numsurfacelist++] = surfaces + j;
12542         }
12543         // update lightmaps if needed
12544         if (model->brushq1.firstrender)
12545         {
12546                 model->brushq1.firstrender = false;
12547                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12548                         if (update[j])
12549                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12550         }
12551         else if (update)
12552         {
12553                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12554                         if (r_refdef.viewcache.world_surfacevisible[j])
12555                                 if (update[j])
12556                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12557         }
12558         // don't do anything if there were no surfaces
12559         if (!numsurfacelist)
12560         {
12561                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12562                 return;
12563         }
12564         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12565
12566         // add to stats if desired
12567         if (r_speeds.integer && !skysurfaces && !depthonly)
12568         {
12569                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12570                 for (j = 0;j < numsurfacelist;j++)
12571                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12572         }
12573
12574         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12575 }
12576
12577 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12578 {
12579         int i, j, endj, flagsmask;
12580         dp_model_t *model = ent->model;
12581         msurface_t *surfaces;
12582         unsigned char *update;
12583         int numsurfacelist = 0;
12584         if (model == NULL)
12585                 return;
12586
12587         if (r_maxsurfacelist < model->num_surfaces)
12588         {
12589                 r_maxsurfacelist = model->num_surfaces;
12590                 if (r_surfacelist)
12591                         Mem_Free((msurface_t **)r_surfacelist);
12592                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12593         }
12594
12595         // if the model is static it doesn't matter what value we give for
12596         // wantnormals and wanttangents, so this logic uses only rules applicable
12597         // to a model, knowing that they are meaningless otherwise
12598         if (ent == r_refdef.scene.worldentity)
12599                 RSurf_ActiveWorldEntity();
12600         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12601                 RSurf_ActiveModelEntity(ent, false, false, false);
12602         else if (prepass)
12603                 RSurf_ActiveModelEntity(ent, true, true, true);
12604         else if (depthonly)
12605         {
12606                 switch (vid.renderpath)
12607                 {
12608                 case RENDERPATH_GL20:
12609                 case RENDERPATH_D3D9:
12610                 case RENDERPATH_D3D10:
12611                 case RENDERPATH_D3D11:
12612                 case RENDERPATH_SOFT:
12613                 case RENDERPATH_GLES2:
12614                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12615                         break;
12616                 case RENDERPATH_GL11:
12617                 case RENDERPATH_GL13:
12618                 case RENDERPATH_GLES1:
12619                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12620                         break;
12621                 }
12622         }
12623         else
12624         {
12625                 switch (vid.renderpath)
12626                 {
12627                 case RENDERPATH_GL20:
12628                 case RENDERPATH_D3D9:
12629                 case RENDERPATH_D3D10:
12630                 case RENDERPATH_D3D11:
12631                 case RENDERPATH_SOFT:
12632                 case RENDERPATH_GLES2:
12633                         RSurf_ActiveModelEntity(ent, true, true, false);
12634                         break;
12635                 case RENDERPATH_GL11:
12636                 case RENDERPATH_GL13:
12637                 case RENDERPATH_GLES1:
12638                         RSurf_ActiveModelEntity(ent, true, false, false);
12639                         break;
12640                 }
12641         }
12642
12643         surfaces = model->data_surfaces;
12644         update = model->brushq1.lightmapupdateflags;
12645
12646         // update light styles
12647         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12648         {
12649                 model_brush_lightstyleinfo_t *style;
12650                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12651                 {
12652                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12653                         {
12654                                 int *list = style->surfacelist;
12655                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12656                                 for (j = 0;j < style->numsurfaces;j++)
12657                                         update[list[j]] = true;
12658                         }
12659                 }
12660         }
12661
12662         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12663
12664         if (debug)
12665         {
12666                 R_DrawDebugModel();
12667                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12668                 return;
12669         }
12670
12671         rsurface.lightmaptexture = NULL;
12672         rsurface.deluxemaptexture = NULL;
12673         rsurface.uselightmaptexture = false;
12674         rsurface.texture = NULL;
12675         rsurface.rtlight = NULL;
12676         numsurfacelist = 0;
12677         // add visible surfaces to draw list
12678         for (i = 0;i < model->nummodelsurfaces;i++)
12679                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12680         // don't do anything if there were no surfaces
12681         if (!numsurfacelist)
12682         {
12683                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12684                 return;
12685         }
12686         // update lightmaps if needed
12687         if (update)
12688         {
12689                 int updated = 0;
12690                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12691                 {
12692                         if (update[j])
12693                         {
12694                                 updated++;
12695                                 R_BuildLightMap(ent, surfaces + j);
12696                         }
12697                 }
12698         }
12699
12700         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12701
12702         // add to stats if desired
12703         if (r_speeds.integer && !skysurfaces && !depthonly)
12704         {
12705                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12706                 for (j = 0;j < numsurfacelist;j++)
12707                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12708         }
12709
12710         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12711 }
12712
12713 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12714 {
12715         static texture_t texture;
12716         static msurface_t surface;
12717         const msurface_t *surfacelist = &surface;
12718
12719         // fake enough texture and surface state to render this geometry
12720
12721         texture.update_lastrenderframe = -1; // regenerate this texture
12722         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12723         texture.currentskinframe = skinframe;
12724         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12725         texture.offsetmapping = OFFSETMAPPING_OFF;
12726         texture.offsetscale = 1;
12727         texture.specularscalemod = 1;
12728         texture.specularpowermod = 1;
12729         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12730         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12731         // JUST GREP FOR "specularscalemod = 1".
12732
12733         surface.texture = &texture;
12734         surface.num_triangles = numtriangles;
12735         surface.num_firsttriangle = firsttriangle;
12736         surface.num_vertices = numvertices;
12737         surface.num_firstvertex = firstvertex;
12738
12739         // now render it
12740         rsurface.texture = R_GetCurrentTexture(surface.texture);
12741         rsurface.lightmaptexture = NULL;
12742         rsurface.deluxemaptexture = NULL;
12743         rsurface.uselightmaptexture = false;
12744         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12745 }
12746
12747 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)
12748 {
12749         static msurface_t surface;
12750         const msurface_t *surfacelist = &surface;
12751
12752         // fake enough texture and surface state to render this geometry
12753         surface.texture = texture;
12754         surface.num_triangles = numtriangles;
12755         surface.num_firsttriangle = firsttriangle;
12756         surface.num_vertices = numvertices;
12757         surface.num_firstvertex = firstvertex;
12758
12759         // now render it
12760         rsurface.texture = R_GetCurrentTexture(surface.texture);
12761         rsurface.lightmaptexture = NULL;
12762         rsurface.deluxemaptexture = NULL;
12763         rsurface.uselightmaptexture = false;
12764         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12765 }