]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
restore the wrapping behavior on tcMod scroll for compatibility reasons
[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 };
885 #define SHADERSTATICPARMS_COUNT 13
886
887 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
888 static int shaderstaticparms_count = 0;
889
890 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
891 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
892
893 extern qboolean r_shadow_shadowmapsampler;
894 extern int r_shadow_shadowmappcf;
895 qboolean R_CompileShader_CheckStaticParms(void)
896 {
897         static int r_compileshader_staticparms_save[1];
898         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
899         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
900
901         // detect all
902         if (r_glsl_saturation_redcompensate.integer)
903                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
904         if (r_glsl_vertextextureblend_usebothalphas.integer)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
906         if (r_shadow_glossexact.integer)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
908         if (r_glsl_postprocess.integer)
909         {
910                 if (r_glsl_postprocess_uservec1_enable.integer)
911                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
912                 if (r_glsl_postprocess_uservec2_enable.integer)
913                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
914                 if (r_glsl_postprocess_uservec3_enable.integer)
915                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
916                 if (r_glsl_postprocess_uservec4_enable.integer)
917                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
918         }
919         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
920                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
921
922         if (r_shadow_shadowmapsampler)
923                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
924         if (r_shadow_shadowmappcf > 1)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
926         else if (r_shadow_shadowmappcf)
927                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
928         if (r_celshading.integer)
929                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
930         if (r_celoutlines.integer)
931                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
932
933         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
934 }
935
936 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
937         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
938                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
939         else \
940                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
941 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
942 {
943         shaderstaticparms_count = 0;
944
945         // emit all
946         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
947         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
948         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
949         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
950         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
951         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
952         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
953         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
954         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
955         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
956         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
957         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
958         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
959 }
960
961 /// information about each possible shader permutation
962 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
963 /// currently selected permutation
964 r_glsl_permutation_t *r_glsl_permutation;
965 /// storage for permutations linked in the hash table
966 memexpandablearray_t r_glsl_permutationarray;
967
968 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
969 {
970         //unsigned int hashdepth = 0;
971         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
972         r_glsl_permutation_t *p;
973         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
974         {
975                 if (p->mode == mode && p->permutation == permutation)
976                 {
977                         //if (hashdepth > 10)
978                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
979                         return p;
980                 }
981                 //hashdepth++;
982         }
983         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
984         p->mode = mode;
985         p->permutation = permutation;
986         p->hashnext = r_glsl_permutationhash[mode][hashindex];
987         r_glsl_permutationhash[mode][hashindex] = p;
988         //if (hashdepth > 10)
989         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
990         return p;
991 }
992
993 static char *R_ShaderStrCat(const char **strings)
994 {
995         char *string, *s;
996         const char **p = strings;
997         const char *t;
998         size_t len = 0;
999         for (p = strings;(t = *p);p++)
1000                 len += strlen(t);
1001         len++;
1002         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1003         len = 0;
1004         for (p = strings;(t = *p);p++)
1005         {
1006                 len = strlen(t);
1007                 memcpy(s, t, len);
1008                 s += len;
1009         }
1010         *s = 0;
1011         return string;
1012 }
1013
1014 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1015 {
1016         char *shaderstring;
1017         if (!filename || !filename[0])
1018                 return NULL;
1019         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1020         if (!strcmp(filename, "glsl/default.glsl"))
1021         {
1022                 if (builtinonly)
1023                         return R_ShaderStrCat(builtinshaderstrings);
1024                 if (!glslshaderstring)
1025                 {
1026                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1027                         if (glslshaderstring)
1028                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1029                         else
1030                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1031                 }
1032                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1033                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1034                 return shaderstring;
1035         }
1036         if (!strcmp(filename, "hlsl/default.hlsl"))
1037         {
1038                 if (builtinonly)
1039                         return R_ShaderStrCat(builtinhlslshaderstrings);
1040                 if (!hlslshaderstring)
1041                 {
1042                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1043                         if (hlslshaderstring)
1044                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1045                         else
1046                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1047                 }
1048                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1049                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1050                 return shaderstring;
1051         }
1052         // we don't have builtin strings for any other files
1053         if (builtinonly)
1054                 return NULL;
1055         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1056         if (shaderstring)
1057         {
1058                 if (printfromdisknotice)
1059                         Con_DPrintf("from disk %s... ", filename);
1060                 return shaderstring;
1061         }
1062         return shaderstring;
1063 }
1064
1065 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1066 {
1067         int i;
1068         int ubibind;
1069         int sampler;
1070         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1071         char *sourcestring;
1072         char permutationname[256];
1073         int vertstrings_count = 0;
1074         int geomstrings_count = 0;
1075         int fragstrings_count = 0;
1076         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1077         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1078         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1079
1080         if (p->compiled)
1081                 return;
1082         p->compiled = true;
1083         p->program = 0;
1084
1085         permutationname[0] = 0;
1086         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1087
1088         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1089
1090         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1091         if(vid.support.glshaderversion >= 140)
1092         {
1093                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1094                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1095                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1096                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1097                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1098                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1099         }
1100         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1101         else if(vid.support.glshaderversion >= 130)
1102         {
1103                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1104                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1105                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1106                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1107                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1108                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1109         }
1110
1111         // the first pretext is which type of shader to compile as
1112         // (later these will all be bound together as a program object)
1113         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1114         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1115         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1116
1117         // the second pretext is the mode (for example a light source)
1118         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1119         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1120         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1121         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1122
1123         // now add all the permutation pretexts
1124         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1125         {
1126                 if (permutation & (1<<i))
1127                 {
1128                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1129                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1130                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1131                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1132                 }
1133                 else
1134                 {
1135                         // keep line numbers correct
1136                         vertstrings_list[vertstrings_count++] = "\n";
1137                         geomstrings_list[geomstrings_count++] = "\n";
1138                         fragstrings_list[fragstrings_count++] = "\n";
1139                 }
1140         }
1141
1142         // add static parms
1143         R_CompileShader_AddStaticParms(mode, permutation);
1144         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1145         vertstrings_count += shaderstaticparms_count;
1146         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1147         geomstrings_count += shaderstaticparms_count;
1148         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1149         fragstrings_count += shaderstaticparms_count;
1150
1151         // now append the shader text itself
1152         vertstrings_list[vertstrings_count++] = sourcestring;
1153         geomstrings_list[geomstrings_count++] = sourcestring;
1154         fragstrings_list[fragstrings_count++] = sourcestring;
1155
1156         // compile the shader program
1157         if (vertstrings_count + geomstrings_count + fragstrings_count)
1158                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1159         if (p->program)
1160         {
1161                 CHECKGLERROR
1162                 qglUseProgram(p->program);CHECKGLERROR
1163                 // look up all the uniform variable names we care about, so we don't
1164                 // have to look them up every time we set them
1165
1166 #if 0
1167                 // debugging aid
1168                 {
1169                         GLint activeuniformindex = 0;
1170                         GLint numactiveuniforms = 0;
1171                         char uniformname[128];
1172                         GLsizei uniformnamelength = 0;
1173                         GLint uniformsize = 0;
1174                         GLenum uniformtype = 0;
1175                         memset(uniformname, 0, sizeof(uniformname));
1176                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1177                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1178                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1179                         {
1180                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1181                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1182                         }
1183                 }
1184 #endif
1185
1186                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1187                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1188                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1189                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1190                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1191                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1192                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1193                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1194                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1195                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1196                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1197                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1198                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1199                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1200                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1201                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1202                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1203                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1204                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1205                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1206                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1207                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1208                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1209                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1210                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1211                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1212                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1213                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1214                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1215                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1216                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1217                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1218                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1219                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1220                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1221                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1222                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1223                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1224                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1225                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1226                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1227                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1228                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1229                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1230                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1231                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1232                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1233                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1234                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1235                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1236                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1237                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1238                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1239                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1240                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1241                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1242                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1243                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1244                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1245                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1246                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1247                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1248                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1249                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1250                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1251                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1252                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1253                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1254                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1255                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1256                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1257                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1258                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1259                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1260                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1261                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1262                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1263                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1264                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1265                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1266                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1267                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1268                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1269                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1270                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1271                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1272                 // initialize the samplers to refer to the texture units we use
1273                 p->tex_Texture_First = -1;
1274                 p->tex_Texture_Second = -1;
1275                 p->tex_Texture_GammaRamps = -1;
1276                 p->tex_Texture_Normal = -1;
1277                 p->tex_Texture_Color = -1;
1278                 p->tex_Texture_Gloss = -1;
1279                 p->tex_Texture_Glow = -1;
1280                 p->tex_Texture_SecondaryNormal = -1;
1281                 p->tex_Texture_SecondaryColor = -1;
1282                 p->tex_Texture_SecondaryGloss = -1;
1283                 p->tex_Texture_SecondaryGlow = -1;
1284                 p->tex_Texture_Pants = -1;
1285                 p->tex_Texture_Shirt = -1;
1286                 p->tex_Texture_FogHeightTexture = -1;
1287                 p->tex_Texture_FogMask = -1;
1288                 p->tex_Texture_Lightmap = -1;
1289                 p->tex_Texture_Deluxemap = -1;
1290                 p->tex_Texture_Attenuation = -1;
1291                 p->tex_Texture_Cube = -1;
1292                 p->tex_Texture_Refraction = -1;
1293                 p->tex_Texture_Reflection = -1;
1294                 p->tex_Texture_ShadowMap2D = -1;
1295                 p->tex_Texture_CubeProjection = -1;
1296                 p->tex_Texture_ScreenNormalMap = -1;
1297                 p->tex_Texture_ScreenDiffuse = -1;
1298                 p->tex_Texture_ScreenSpecular = -1;
1299                 p->tex_Texture_ReflectMask = -1;
1300                 p->tex_Texture_ReflectCube = -1;
1301                 p->tex_Texture_BounceGrid = -1;
1302                 // bind the texture samplers in use
1303                 sampler = 0;
1304                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1305                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1306                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1307                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1308                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1309                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1310                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1311                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1312                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1313                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1314                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1315                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1316                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1317                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1318                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1319                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1320                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1321                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1322                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1323                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1324                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1325                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1326                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1327                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1328                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1329                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1330                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1331                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1332                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1333                 // get the uniform block indices so we can bind them
1334 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1335                 if (vid.support.arb_uniform_buffer_object)
1336                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1337                 else
1338 #endif
1339                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1340                 // clear the uniform block bindings
1341                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1342                 // bind the uniform blocks in use
1343                 ubibind = 0;
1344 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1345                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1346 #endif
1347                 // we're done compiling and setting up the shader, at least until it is used
1348                 CHECKGLERROR
1349                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1350         }
1351         else
1352                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1353
1354         // free the strings
1355         if (sourcestring)
1356                 Mem_Free(sourcestring);
1357 }
1358
1359 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1360 {
1361         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1362         if (r_glsl_permutation != perm)
1363         {
1364                 r_glsl_permutation = perm;
1365                 if (!r_glsl_permutation->program)
1366                 {
1367                         if (!r_glsl_permutation->compiled)
1368                         {
1369                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1370                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1371                         }
1372                         if (!r_glsl_permutation->program)
1373                         {
1374                                 // remove features until we find a valid permutation
1375                                 int i;
1376                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1377                                 {
1378                                         // reduce i more quickly whenever it would not remove any bits
1379                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1380                                         if (!(permutation & j))
1381                                                 continue;
1382                                         permutation -= j;
1383                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1384                                         if (!r_glsl_permutation->compiled)
1385                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1386                                         if (r_glsl_permutation->program)
1387                                                 break;
1388                                 }
1389                                 if (i >= SHADERPERMUTATION_COUNT)
1390                                 {
1391                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1392                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1393                                         qglUseProgram(0);CHECKGLERROR
1394                                         return; // no bit left to clear, entire mode is broken
1395                                 }
1396                         }
1397                 }
1398                 CHECKGLERROR
1399                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1400         }
1401         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1402         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1403         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1404         CHECKGLERROR
1405 }
1406
1407 #ifdef SUPPORTD3D
1408
1409 #ifdef SUPPORTD3D
1410 #include <d3d9.h>
1411 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1412 extern D3DCAPS9 vid_d3d9caps;
1413 #endif
1414
1415 struct r_hlsl_permutation_s;
1416 typedef struct r_hlsl_permutation_s
1417 {
1418         /// hash lookup data
1419         struct r_hlsl_permutation_s *hashnext;
1420         unsigned int mode;
1421         unsigned int permutation;
1422
1423         /// indicates if we have tried compiling this permutation already
1424         qboolean compiled;
1425         /// NULL if compilation failed
1426         IDirect3DVertexShader9 *vertexshader;
1427         IDirect3DPixelShader9 *pixelshader;
1428 }
1429 r_hlsl_permutation_t;
1430
1431 typedef enum D3DVSREGISTER_e
1432 {
1433         D3DVSREGISTER_TexMatrix = 0, // float4x4
1434         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1435         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1436         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1437         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1438         D3DVSREGISTER_ModelToLight = 20, // float4x4
1439         D3DVSREGISTER_EyePosition = 24,
1440         D3DVSREGISTER_FogPlane = 25,
1441         D3DVSREGISTER_LightDir = 26,
1442         D3DVSREGISTER_LightPosition = 27,
1443 }
1444 D3DVSREGISTER_t;
1445
1446 typedef enum D3DPSREGISTER_e
1447 {
1448         D3DPSREGISTER_Alpha = 0,
1449         D3DPSREGISTER_BloomBlur_Parameters = 1,
1450         D3DPSREGISTER_ClientTime = 2,
1451         D3DPSREGISTER_Color_Ambient = 3,
1452         D3DPSREGISTER_Color_Diffuse = 4,
1453         D3DPSREGISTER_Color_Specular = 5,
1454         D3DPSREGISTER_Color_Glow = 6,
1455         D3DPSREGISTER_Color_Pants = 7,
1456         D3DPSREGISTER_Color_Shirt = 8,
1457         D3DPSREGISTER_DeferredColor_Ambient = 9,
1458         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1459         D3DPSREGISTER_DeferredColor_Specular = 11,
1460         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1461         D3DPSREGISTER_DeferredMod_Specular = 13,
1462         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1463         D3DPSREGISTER_EyePosition = 15, // unused
1464         D3DPSREGISTER_FogColor = 16,
1465         D3DPSREGISTER_FogHeightFade = 17,
1466         D3DPSREGISTER_FogPlane = 18,
1467         D3DPSREGISTER_FogPlaneViewDist = 19,
1468         D3DPSREGISTER_FogRangeRecip = 20,
1469         D3DPSREGISTER_LightColor = 21,
1470         D3DPSREGISTER_LightDir = 22, // unused
1471         D3DPSREGISTER_LightPosition = 23,
1472         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1473         D3DPSREGISTER_PixelSize = 25,
1474         D3DPSREGISTER_ReflectColor = 26,
1475         D3DPSREGISTER_ReflectFactor = 27,
1476         D3DPSREGISTER_ReflectOffset = 28,
1477         D3DPSREGISTER_RefractColor = 29,
1478         D3DPSREGISTER_Saturation = 30,
1479         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1480         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1481         D3DPSREGISTER_ScreenToDepth = 33,
1482         D3DPSREGISTER_ShadowMap_Parameters = 34,
1483         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1484         D3DPSREGISTER_SpecularPower = 36,
1485         D3DPSREGISTER_UserVec1 = 37,
1486         D3DPSREGISTER_UserVec2 = 38,
1487         D3DPSREGISTER_UserVec3 = 39,
1488         D3DPSREGISTER_UserVec4 = 40,
1489         D3DPSREGISTER_ViewTintColor = 41,
1490         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1491         D3DPSREGISTER_BloomColorSubtract = 43,
1492         D3DPSREGISTER_ViewToLight = 44, // float4x4
1493         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1494         D3DPSREGISTER_NormalmapScrollBlend = 52,
1495         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1496         D3DPSREGISTER_OffsetMapping_Bias = 54,
1497         // next at 54
1498 }
1499 D3DPSREGISTER_t;
1500
1501 /// information about each possible shader permutation
1502 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1503 /// currently selected permutation
1504 r_hlsl_permutation_t *r_hlsl_permutation;
1505 /// storage for permutations linked in the hash table
1506 memexpandablearray_t r_hlsl_permutationarray;
1507
1508 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1509 {
1510         //unsigned int hashdepth = 0;
1511         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1512         r_hlsl_permutation_t *p;
1513         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1514         {
1515                 if (p->mode == mode && p->permutation == permutation)
1516                 {
1517                         //if (hashdepth > 10)
1518                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1519                         return p;
1520                 }
1521                 //hashdepth++;
1522         }
1523         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1524         p->mode = mode;
1525         p->permutation = permutation;
1526         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1527         r_hlsl_permutationhash[mode][hashindex] = p;
1528         //if (hashdepth > 10)
1529         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1530         return p;
1531 }
1532
1533 #include <d3dx9.h>
1534 //#include <d3dx9shader.h>
1535 //#include <d3dx9mesh.h>
1536
1537 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1538 {
1539         DWORD *vsbin = NULL;
1540         DWORD *psbin = NULL;
1541         fs_offset_t vsbinsize;
1542         fs_offset_t psbinsize;
1543 //      IDirect3DVertexShader9 *vs = NULL;
1544 //      IDirect3DPixelShader9 *ps = NULL;
1545         ID3DXBuffer *vslog = NULL;
1546         ID3DXBuffer *vsbuffer = NULL;
1547         ID3DXConstantTable *vsconstanttable = NULL;
1548         ID3DXBuffer *pslog = NULL;
1549         ID3DXBuffer *psbuffer = NULL;
1550         ID3DXConstantTable *psconstanttable = NULL;
1551         int vsresult = 0;
1552         int psresult = 0;
1553         char temp[MAX_INPUTLINE];
1554         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1555         char vabuf[1024];
1556         qboolean debugshader = gl_paranoid.integer != 0;
1557         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1558         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1559         if (!debugshader)
1560         {
1561                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1562                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1563         }
1564         if ((!vsbin && vertstring) || (!psbin && fragstring))
1565         {
1566                 const char* dllnames_d3dx9 [] =
1567                 {
1568                         "d3dx9_43.dll",
1569                         "d3dx9_42.dll",
1570                         "d3dx9_41.dll",
1571                         "d3dx9_40.dll",
1572                         "d3dx9_39.dll",
1573                         "d3dx9_38.dll",
1574                         "d3dx9_37.dll",
1575                         "d3dx9_36.dll",
1576                         "d3dx9_35.dll",
1577                         "d3dx9_34.dll",
1578                         "d3dx9_33.dll",
1579                         "d3dx9_32.dll",
1580                         "d3dx9_31.dll",
1581                         "d3dx9_30.dll",
1582                         "d3dx9_29.dll",
1583                         "d3dx9_28.dll",
1584                         "d3dx9_27.dll",
1585                         "d3dx9_26.dll",
1586                         "d3dx9_25.dll",
1587                         "d3dx9_24.dll",
1588                         NULL
1589                 };
1590                 dllhandle_t d3dx9_dll = NULL;
1591                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1592                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1593                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1594                 dllfunction_t d3dx9_dllfuncs[] =
1595                 {
1596                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1597                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1598                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1599                         {NULL, NULL}
1600                 };
1601                 // 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...
1602 #ifndef ID3DXBuffer_GetBufferPointer
1603 #if !defined(__cplusplus) || defined(CINTERFACE)
1604 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1605 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1606 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1607 #else
1608 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1609 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1610 #define ID3DXBuffer_Release(p)            (p)->Release()
1611 #endif
1612 #endif
1613                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1614                 {
1615                         DWORD shaderflags = 0;
1616                         if (debugshader)
1617                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1618                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1619                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1620                         if (vertstring && vertstring[0])
1621                         {
1622                                 if (debugshader)
1623                                 {
1624                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1625                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1626                                 }
1627                                 else
1628                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1629                                 if (vsbuffer)
1630                                 {
1631                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1632                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1633                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1634                                         ID3DXBuffer_Release(vsbuffer);
1635                                 }
1636                                 if (vslog)
1637                                 {
1638                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1639                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1640                                         ID3DXBuffer_Release(vslog);
1641                                 }
1642                         }
1643                         if (fragstring && fragstring[0])
1644                         {
1645                                 if (debugshader)
1646                                 {
1647                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1648                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1649                                 }
1650                                 else
1651                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1652                                 if (psbuffer)
1653                                 {
1654                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1655                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1656                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1657                                         ID3DXBuffer_Release(psbuffer);
1658                                 }
1659                                 if (pslog)
1660                                 {
1661                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1662                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1663                                         ID3DXBuffer_Release(pslog);
1664                                 }
1665                         }
1666                         Sys_UnloadLibrary(&d3dx9_dll);
1667                 }
1668                 else
1669                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1670         }
1671         if (vsbin && psbin)
1672         {
1673                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1674                 if (FAILED(vsresult))
1675                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1676                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1677                 if (FAILED(psresult))
1678                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1679         }
1680         // free the shader data
1681         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1682         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1683 }
1684
1685 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1686 {
1687         int i;
1688         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1689         int vertstring_length = 0;
1690         int geomstring_length = 0;
1691         int fragstring_length = 0;
1692         char *t;
1693         char *sourcestring;
1694         char *vertstring, *geomstring, *fragstring;
1695         char permutationname[256];
1696         char cachename[256];
1697         int vertstrings_count = 0;
1698         int geomstrings_count = 0;
1699         int fragstrings_count = 0;
1700         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1701         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1702         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1703
1704         if (p->compiled)
1705                 return;
1706         p->compiled = true;
1707         p->vertexshader = NULL;
1708         p->pixelshader = NULL;
1709
1710         permutationname[0] = 0;
1711         cachename[0] = 0;
1712         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1713
1714         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1715         strlcat(cachename, "hlsl/", sizeof(cachename));
1716
1717         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1718         vertstrings_count = 0;
1719         geomstrings_count = 0;
1720         fragstrings_count = 0;
1721         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1722         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1723         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1724
1725         // the first pretext is which type of shader to compile as
1726         // (later these will all be bound together as a program object)
1727         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1728         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1729         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1730
1731         // the second pretext is the mode (for example a light source)
1732         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1733         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1734         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1735         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1736         strlcat(cachename, modeinfo->name, sizeof(cachename));
1737
1738         // now add all the permutation pretexts
1739         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1740         {
1741                 if (permutation & (1<<i))
1742                 {
1743                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1744                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1745                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1746                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1747                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1748                 }
1749                 else
1750                 {
1751                         // keep line numbers correct
1752                         vertstrings_list[vertstrings_count++] = "\n";
1753                         geomstrings_list[geomstrings_count++] = "\n";
1754                         fragstrings_list[fragstrings_count++] = "\n";
1755                 }
1756         }
1757
1758         // add static parms
1759         R_CompileShader_AddStaticParms(mode, permutation);
1760         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1761         vertstrings_count += shaderstaticparms_count;
1762         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1763         geomstrings_count += shaderstaticparms_count;
1764         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1765         fragstrings_count += shaderstaticparms_count;
1766
1767         // replace spaces in the cachename with _ characters
1768         for (i = 0;cachename[i];i++)
1769                 if (cachename[i] == ' ')
1770                         cachename[i] = '_';
1771
1772         // now append the shader text itself
1773         vertstrings_list[vertstrings_count++] = sourcestring;
1774         geomstrings_list[geomstrings_count++] = sourcestring;
1775         fragstrings_list[fragstrings_count++] = sourcestring;
1776
1777         vertstring_length = 0;
1778         for (i = 0;i < vertstrings_count;i++)
1779                 vertstring_length += strlen(vertstrings_list[i]);
1780         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1781         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1782                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1783
1784         geomstring_length = 0;
1785         for (i = 0;i < geomstrings_count;i++)
1786                 geomstring_length += strlen(geomstrings_list[i]);
1787         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1788         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1789                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1790
1791         fragstring_length = 0;
1792         for (i = 0;i < fragstrings_count;i++)
1793                 fragstring_length += strlen(fragstrings_list[i]);
1794         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1795         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1796                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1797
1798         // try to load the cached shader, or generate one
1799         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1800
1801         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1802                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1803         else
1804                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1805
1806         // free the strings
1807         if (vertstring)
1808                 Mem_Free(vertstring);
1809         if (geomstring)
1810                 Mem_Free(geomstring);
1811         if (fragstring)
1812                 Mem_Free(fragstring);
1813         if (sourcestring)
1814                 Mem_Free(sourcestring);
1815 }
1816
1817 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1818 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1819 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);}
1820 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);}
1821 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);}
1822 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);}
1823
1824 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1825 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1826 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);}
1827 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);}
1828 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);}
1829 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);}
1830
1831 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1832 {
1833         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1834         if (r_hlsl_permutation != perm)
1835         {
1836                 r_hlsl_permutation = perm;
1837                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1838                 {
1839                         if (!r_hlsl_permutation->compiled)
1840                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1841                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1842                         {
1843                                 // remove features until we find a valid permutation
1844                                 int i;
1845                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1846                                 {
1847                                         // reduce i more quickly whenever it would not remove any bits
1848                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1849                                         if (!(permutation & j))
1850                                                 continue;
1851                                         permutation -= j;
1852                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1853                                         if (!r_hlsl_permutation->compiled)
1854                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1855                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1856                                                 break;
1857                                 }
1858                                 if (i >= SHADERPERMUTATION_COUNT)
1859                                 {
1860                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1861                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1862                                         return; // no bit left to clear, entire mode is broken
1863                                 }
1864                         }
1865                 }
1866                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1867                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1868         }
1869         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1870         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1871         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1872 }
1873 #endif
1874
1875 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1876 {
1877         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1878         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1879         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1880         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1881 }
1882
1883 void R_GLSL_Restart_f(void)
1884 {
1885         unsigned int i, limit;
1886         if (glslshaderstring)
1887                 Mem_Free(glslshaderstring);
1888         glslshaderstring = NULL;
1889         if (hlslshaderstring)
1890                 Mem_Free(hlslshaderstring);
1891         hlslshaderstring = NULL;
1892         switch(vid.renderpath)
1893         {
1894         case RENDERPATH_D3D9:
1895 #ifdef SUPPORTD3D
1896                 {
1897                         r_hlsl_permutation_t *p;
1898                         r_hlsl_permutation = NULL;
1899                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1900                         for (i = 0;i < limit;i++)
1901                         {
1902                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1903                                 {
1904                                         if (p->vertexshader)
1905                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1906                                         if (p->pixelshader)
1907                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1908                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1909                                 }
1910                         }
1911                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1912                 }
1913 #endif
1914                 break;
1915         case RENDERPATH_D3D10:
1916                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1917                 break;
1918         case RENDERPATH_D3D11:
1919                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920                 break;
1921         case RENDERPATH_GL20:
1922         case RENDERPATH_GLES2:
1923                 {
1924                         r_glsl_permutation_t *p;
1925                         r_glsl_permutation = NULL;
1926                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1927                         for (i = 0;i < limit;i++)
1928                         {
1929                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1930                                 {
1931                                         GL_Backend_FreeProgram(p->program);
1932                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1933                                 }
1934                         }
1935                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1936                 }
1937                 break;
1938         case RENDERPATH_GL11:
1939         case RENDERPATH_GL13:
1940         case RENDERPATH_GLES1:
1941                 break;
1942         case RENDERPATH_SOFT:
1943                 break;
1944         }
1945 }
1946
1947 static void R_GLSL_DumpShader_f(void)
1948 {
1949         int i, language, mode, dupe;
1950         char *text;
1951         shadermodeinfo_t *modeinfo;
1952         qfile_t *file;
1953
1954         for (language = 0;language < 2;language++)
1955         {
1956                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1957                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1958                 {
1959                         // don't dump the same file multiple times (most or all shaders come from the same file)
1960                         for (dupe = mode - 1;dupe >= 0;dupe--)
1961                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1962                                         break;
1963                         if (dupe >= 0)
1964                                 continue;
1965                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1966                         if (!text)
1967                                 continue;
1968                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1969                         if (file)
1970                         {
1971                                 FS_Print(file, "/* The engine may define the following macros:\n");
1972                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1973                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1974                                         FS_Print(file, modeinfo[i].pretext);
1975                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1976                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1977                                 FS_Print(file, "*/\n");
1978                                 FS_Print(file, text);
1979                                 FS_Close(file);
1980                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1981                         }
1982                         else
1983                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1984                         Mem_Free(text);
1985                 }
1986         }
1987 }
1988
1989 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1990 {
1991         unsigned int permutation = 0;
1992         if (r_trippy.integer && !notrippy)
1993                 permutation |= SHADERPERMUTATION_TRIPPY;
1994         permutation |= SHADERPERMUTATION_VIEWTINT;
1995         if (first)
1996                 permutation |= SHADERPERMUTATION_DIFFUSE;
1997         if (second)
1998                 permutation |= SHADERPERMUTATION_SPECULAR;
1999         if (texturemode == GL_MODULATE)
2000                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2001         else if (texturemode == GL_ADD)
2002                 permutation |= SHADERPERMUTATION_GLOW;
2003         else if (texturemode == GL_DECAL)
2004                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2005         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2006                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2007         if (suppresstexalpha)
2008                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2009         if (!second)
2010                 texturemode = GL_MODULATE;
2011         if (vid.allowalphatocoverage)
2012                 GL_AlphaToCoverage(false);
2013         switch (vid.renderpath)
2014         {
2015         case RENDERPATH_D3D9:
2016 #ifdef SUPPORTD3D
2017                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2018                 R_Mesh_TexBind(GL20TU_FIRST , first );
2019                 R_Mesh_TexBind(GL20TU_SECOND, second);
2020                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2021                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2022 #endif
2023                 break;
2024         case RENDERPATH_D3D10:
2025                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2026                 break;
2027         case RENDERPATH_D3D11:
2028                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2029                 break;
2030         case RENDERPATH_GL20:
2031         case RENDERPATH_GLES2:
2032                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2033                 if (r_glsl_permutation->tex_Texture_First >= 0)
2034                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2035                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2036                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2037                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2038                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2039                 break;
2040         case RENDERPATH_GL13:
2041         case RENDERPATH_GLES1:
2042                 R_Mesh_TexBind(0, first );
2043                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2044                 R_Mesh_TexMatrix(0, NULL);
2045                 R_Mesh_TexBind(1, second);
2046                 if (second)
2047                 {
2048                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2049                         R_Mesh_TexMatrix(1, NULL);
2050                 }
2051                 break;
2052         case RENDERPATH_GL11:
2053                 R_Mesh_TexBind(0, first );
2054                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2055                 R_Mesh_TexMatrix(0, NULL);
2056                 break;
2057         case RENDERPATH_SOFT:
2058                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2059                 R_Mesh_TexBind(GL20TU_FIRST , first );
2060                 R_Mesh_TexBind(GL20TU_SECOND, second);
2061                 break;
2062         }
2063 }
2064
2065 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2066 {
2067         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2068 }
2069
2070 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2071 {
2072         unsigned int permutation = 0;
2073         if (r_trippy.integer && !notrippy)
2074                 permutation |= SHADERPERMUTATION_TRIPPY;
2075         if (depthrgb)
2076                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2077         if (skeletal)
2078                 permutation |= SHADERPERMUTATION_SKELETAL;
2079
2080         if (vid.allowalphatocoverage)
2081                 GL_AlphaToCoverage(false);
2082         switch (vid.renderpath)
2083         {
2084         case RENDERPATH_D3D9:
2085 #ifdef SUPPORTD3D
2086                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2087 #endif
2088                 break;
2089         case RENDERPATH_D3D10:
2090                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2091                 break;
2092         case RENDERPATH_D3D11:
2093                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2094                 break;
2095         case RENDERPATH_GL20:
2096         case RENDERPATH_GLES2:
2097                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2098 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2099                 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);
2100 #endif
2101                 break;
2102         case RENDERPATH_GL13:
2103         case RENDERPATH_GLES1:
2104                 R_Mesh_TexBind(0, 0);
2105                 R_Mesh_TexBind(1, 0);
2106                 break;
2107         case RENDERPATH_GL11:
2108                 R_Mesh_TexBind(0, 0);
2109                 break;
2110         case RENDERPATH_SOFT:
2111                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2112                 break;
2113         }
2114 }
2115
2116 extern qboolean r_shadow_usingdeferredprepass;
2117 extern rtexture_t *r_shadow_attenuationgradienttexture;
2118 extern rtexture_t *r_shadow_attenuation2dtexture;
2119 extern rtexture_t *r_shadow_attenuation3dtexture;
2120 extern qboolean r_shadow_usingshadowmap2d;
2121 extern qboolean r_shadow_usingshadowmaportho;
2122 extern float r_shadow_shadowmap_texturescale[2];
2123 extern float r_shadow_shadowmap_parameters[4];
2124 extern qboolean r_shadow_shadowmapvsdct;
2125 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2126 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2127 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2128 extern matrix4x4_t r_shadow_shadowmapmatrix;
2129 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2130 extern int r_shadow_prepass_width;
2131 extern int r_shadow_prepass_height;
2132 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2133 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2134 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2135 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2136
2137 #define BLENDFUNC_ALLOWS_COLORMOD      1
2138 #define BLENDFUNC_ALLOWS_FOG           2
2139 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2140 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2141 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2142 static int R_BlendFuncFlags(int src, int dst)
2143 {
2144         int r = 0;
2145
2146         // a blendfunc allows colormod if:
2147         // a) it can never keep the destination pixel invariant, or
2148         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2149         // this is to prevent unintended side effects from colormod
2150
2151         // a blendfunc allows fog if:
2152         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2153         // this is to prevent unintended side effects from fog
2154
2155         // these checks are the output of fogeval.pl
2156
2157         r |= BLENDFUNC_ALLOWS_COLORMOD;
2158         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2159         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2160         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2161         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2162         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2163         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2164         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2165         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2166         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2167         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2168         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2169         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2170         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2171         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2172         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2173         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2174         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2175         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2176         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2177         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2178         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179
2180         return r;
2181 }
2182
2183 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)
2184 {
2185         // select a permutation of the lighting shader appropriate to this
2186         // combination of texture, entity, light source, and fogging, only use the
2187         // minimum features necessary to avoid wasting rendering time in the
2188         // fragment shader on features that are not being used
2189         unsigned int permutation = 0;
2190         unsigned int mode = 0;
2191         int blendfuncflags;
2192         static float dummy_colormod[3] = {1, 1, 1};
2193         float *colormod = rsurface.colormod;
2194         float m16f[16];
2195         matrix4x4_t tempmatrix;
2196         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2197         if (r_trippy.integer && !notrippy)
2198                 permutation |= SHADERPERMUTATION_TRIPPY;
2199         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2200                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2201         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2202                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2203         if (rsurfacepass == RSURFPASS_BACKGROUND)
2204         {
2205                 // distorted background
2206                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2207                 {
2208                         mode = SHADERMODE_WATER;
2209                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2210                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2211                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2212                         {
2213                                 // this is the right thing to do for wateralpha
2214                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2215                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2216                         }
2217                         else
2218                         {
2219                                 // this is the right thing to do for entity alpha
2220                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2221                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2222                         }
2223                 }
2224                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2225                 {
2226                         mode = SHADERMODE_REFRACTION;
2227                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2228                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2229                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2230                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2231                 }
2232                 else
2233                 {
2234                         mode = SHADERMODE_GENERIC;
2235                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2236                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2237                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2238                 }
2239                 if (vid.allowalphatocoverage)
2240                         GL_AlphaToCoverage(false);
2241         }
2242         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2243         {
2244                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2245                 {
2246                         switch(rsurface.texture->offsetmapping)
2247                         {
2248                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2249                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2250                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2251                         case OFFSETMAPPING_OFF: break;
2252                         }
2253                 }
2254                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2255                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2256                 // normalmap (deferred prepass), may use alpha test on diffuse
2257                 mode = SHADERMODE_DEFERREDGEOMETRY;
2258                 GL_BlendFunc(GL_ONE, GL_ZERO);
2259                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2260                 if (vid.allowalphatocoverage)
2261                         GL_AlphaToCoverage(false);
2262         }
2263         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2264         {
2265                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2266                 {
2267                         switch(rsurface.texture->offsetmapping)
2268                         {
2269                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2270                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2271                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2272                         case OFFSETMAPPING_OFF: break;
2273                         }
2274                 }
2275                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2276                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2277                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2278                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2279                 // light source
2280                 mode = SHADERMODE_LIGHTSOURCE;
2281                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2282                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2283                 if (diffusescale > 0)
2284                         permutation |= SHADERPERMUTATION_DIFFUSE;
2285                 if (specularscale > 0)
2286                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2287                 if (r_refdef.fogenabled)
2288                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2289                 if (rsurface.texture->colormapping)
2290                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2291                 if (r_shadow_usingshadowmap2d)
2292                 {
2293                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2294                         if(r_shadow_shadowmapvsdct)
2295                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2296
2297                         if (r_shadow_shadowmap2ddepthbuffer)
2298                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2299                 }
2300                 if (rsurface.texture->reflectmasktexture)
2301                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2302                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2303                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2304                 if (vid.allowalphatocoverage)
2305                         GL_AlphaToCoverage(false);
2306         }
2307         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2308         {
2309                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2310                 {
2311                         switch(rsurface.texture->offsetmapping)
2312                         {
2313                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2314                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2315                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2316                         case OFFSETMAPPING_OFF: break;
2317                         }
2318                 }
2319                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2320                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2321                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2322                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2323                 // unshaded geometry (fullbright or ambient model lighting)
2324                 mode = SHADERMODE_FLATCOLOR;
2325                 ambientscale = diffusescale = specularscale = 0;
2326                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2327                         permutation |= SHADERPERMUTATION_GLOW;
2328                 if (r_refdef.fogenabled)
2329                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2330                 if (rsurface.texture->colormapping)
2331                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2332                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2333                 {
2334                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2335                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2336
2337                         if (r_shadow_shadowmap2ddepthbuffer)
2338                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2339                 }
2340                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2341                         permutation |= SHADERPERMUTATION_REFLECTION;
2342                 if (rsurface.texture->reflectmasktexture)
2343                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2344                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2345                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2346                 // when using alphatocoverage, we don't need alphakill
2347                 if (vid.allowalphatocoverage)
2348                 {
2349                         if (r_transparent_alphatocoverage.integer)
2350                         {
2351                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2352                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2353                         }
2354                         else
2355                                 GL_AlphaToCoverage(false);
2356                 }
2357         }
2358         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2359         {
2360                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2361                 {
2362                         switch(rsurface.texture->offsetmapping)
2363                         {
2364                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2365                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2366                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2367                         case OFFSETMAPPING_OFF: break;
2368                         }
2369                 }
2370                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2371                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2372                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2373                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2374                 // directional model lighting
2375                 mode = SHADERMODE_LIGHTDIRECTION;
2376                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2377                         permutation |= SHADERPERMUTATION_GLOW;
2378                 permutation |= SHADERPERMUTATION_DIFFUSE;
2379                 if (specularscale > 0)
2380                         permutation |= SHADERPERMUTATION_SPECULAR;
2381                 if (r_refdef.fogenabled)
2382                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2383                 if (rsurface.texture->colormapping)
2384                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2385                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2386                 {
2387                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2388                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2389
2390                         if (r_shadow_shadowmap2ddepthbuffer)
2391                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2392                 }
2393                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2394                         permutation |= SHADERPERMUTATION_REFLECTION;
2395                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2396                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2397                 if (rsurface.texture->reflectmasktexture)
2398                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2399                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2400                 {
2401                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2402                         if (r_shadow_bouncegriddirectional)
2403                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2404                 }
2405                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2406                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2407                 // when using alphatocoverage, we don't need alphakill
2408                 if (vid.allowalphatocoverage)
2409                 {
2410                         if (r_transparent_alphatocoverage.integer)
2411                         {
2412                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2413                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2414                         }
2415                         else
2416                                 GL_AlphaToCoverage(false);
2417                 }
2418         }
2419         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2420         {
2421                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2422                 {
2423                         switch(rsurface.texture->offsetmapping)
2424                         {
2425                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2426                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2427                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2428                         case OFFSETMAPPING_OFF: break;
2429                         }
2430                 }
2431                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2432                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2434                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2435                 // ambient model lighting
2436                 mode = SHADERMODE_LIGHTDIRECTION;
2437                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2438                         permutation |= SHADERPERMUTATION_GLOW;
2439                 if (r_refdef.fogenabled)
2440                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2441                 if (rsurface.texture->colormapping)
2442                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2443                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2444                 {
2445                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2446                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2447
2448                         if (r_shadow_shadowmap2ddepthbuffer)
2449                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2450                 }
2451                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2452                         permutation |= SHADERPERMUTATION_REFLECTION;
2453                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2454                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2455                 if (rsurface.texture->reflectmasktexture)
2456                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2457                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2458                 {
2459                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2460                         if (r_shadow_bouncegriddirectional)
2461                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2462                 }
2463                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2464                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2465                 // when using alphatocoverage, we don't need alphakill
2466                 if (vid.allowalphatocoverage)
2467                 {
2468                         if (r_transparent_alphatocoverage.integer)
2469                         {
2470                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2471                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2472                         }
2473                         else
2474                                 GL_AlphaToCoverage(false);
2475                 }
2476         }
2477         else
2478         {
2479                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2480                 {
2481                         switch(rsurface.texture->offsetmapping)
2482                         {
2483                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2484                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2485                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2486                         case OFFSETMAPPING_OFF: break;
2487                         }
2488                 }
2489                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2490                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2491                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2492                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2493                 // lightmapped wall
2494                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2495                         permutation |= SHADERPERMUTATION_GLOW;
2496                 if (r_refdef.fogenabled)
2497                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2498                 if (rsurface.texture->colormapping)
2499                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2500                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2501                 {
2502                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2503                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2504
2505                         if (r_shadow_shadowmap2ddepthbuffer)
2506                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2507                 }
2508                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2509                         permutation |= SHADERPERMUTATION_REFLECTION;
2510                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2511                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2512                 if (rsurface.texture->reflectmasktexture)
2513                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2514                 if (FAKELIGHT_ENABLED)
2515                 {
2516                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2517                         mode = SHADERMODE_FAKELIGHT;
2518                         permutation |= SHADERPERMUTATION_DIFFUSE;
2519                         if (specularscale > 0)
2520                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2521                 }
2522                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2523                 {
2524                         // deluxemapping (light direction texture)
2525                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2526                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2527                         else
2528                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2529                         permutation |= SHADERPERMUTATION_DIFFUSE;
2530                         if (specularscale > 0)
2531                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2532                 }
2533                 else if (r_glsl_deluxemapping.integer >= 2)
2534                 {
2535                         // fake deluxemapping (uniform light direction in tangentspace)
2536                         if (rsurface.uselightmaptexture)
2537                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2538                         else
2539                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2540                         permutation |= SHADERPERMUTATION_DIFFUSE;
2541                         if (specularscale > 0)
2542                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2543                 }
2544                 else if (rsurface.uselightmaptexture)
2545                 {
2546                         // ordinary lightmapping (q1bsp, q3bsp)
2547                         mode = SHADERMODE_LIGHTMAP;
2548                 }
2549                 else
2550                 {
2551                         // ordinary vertex coloring (q3bsp)
2552                         mode = SHADERMODE_VERTEXCOLOR;
2553                 }
2554                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2555                 {
2556                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2557                         if (r_shadow_bouncegriddirectional)
2558                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2559                 }
2560                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2561                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2562                 // when using alphatocoverage, we don't need alphakill
2563                 if (vid.allowalphatocoverage)
2564                 {
2565                         if (r_transparent_alphatocoverage.integer)
2566                         {
2567                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2568                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2569                         }
2570                         else
2571                                 GL_AlphaToCoverage(false);
2572                 }
2573         }
2574         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2575                 colormod = dummy_colormod;
2576         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2577                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2578         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2579                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2580         switch(vid.renderpath)
2581         {
2582         case RENDERPATH_D3D9:
2583 #ifdef SUPPORTD3D
2584                 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);
2585                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2586                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2587                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2588                 if (mode == SHADERMODE_LIGHTSOURCE)
2589                 {
2590                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2591                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2592                 }
2593                 else
2594                 {
2595                         if (mode == SHADERMODE_LIGHTDIRECTION)
2596                         {
2597                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2598                         }
2599                 }
2600                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2601                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2602                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2603                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2604                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2605
2606                 if (mode == SHADERMODE_LIGHTSOURCE)
2607                 {
2608                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2609                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2610                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2611                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2612                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2613
2614                         // additive passes are only darkened by fog, not tinted
2615                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2616                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2617                 }
2618                 else
2619                 {
2620                         if (mode == SHADERMODE_FLATCOLOR)
2621                         {
2622                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2623                         }
2624                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2625                         {
2626                                 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]);
2627                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2628                                 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);
2629                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2630                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2631                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2632                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2633                         }
2634                         else
2635                         {
2636                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2637                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2638                                 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);
2639                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2640                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2641                         }
2642                         // additive passes are only darkened by fog, not tinted
2643                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2644                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2645                         else
2646                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2647                         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);
2648                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2649                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2650                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2651                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2652                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2653                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2654                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2655                         if (mode == SHADERMODE_WATER)
2656                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2657                 }
2658                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2659                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2660                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2661                 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));
2662                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2663                 if (rsurface.texture->pantstexture)
2664                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2665                 else
2666                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2667                 if (rsurface.texture->shirttexture)
2668                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2669                 else
2670                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2671                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2672                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2673                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2674                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2675                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2676                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2677                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2678                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2679                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2680                         );
2681                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2682                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2683                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2684                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2685
2686                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2687                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2688                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2689                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2690                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2691                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2692                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2693                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2694                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2695                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2696                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2697                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2698                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2699                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2700                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2701                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2702                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2703                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2704                 {
2705                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2706                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2707                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2708                 }
2709                 else
2710                 {
2711                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2712                 }
2713 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2714                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2715                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2716                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2717                 {
2718                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2719                         if (rsurface.rtlight)
2720                         {
2721                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2722                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2723                         }
2724                 }
2725 #endif
2726                 break;
2727         case RENDERPATH_D3D10:
2728                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2729                 break;
2730         case RENDERPATH_D3D11:
2731                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2732                 break;
2733         case RENDERPATH_GL20:
2734         case RENDERPATH_GLES2:
2735                 if (!vid.useinterleavedarrays)
2736                 {
2737                         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);
2738                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2739                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2740                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2741                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2742                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2743                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2744                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2745                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2746                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2747                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2748                 }
2749                 else
2750                 {
2751                         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);
2752                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2753                 }
2754                 // this has to be after RSurf_PrepareVerticesForBatch
2755                 if (rsurface.batchskeletaltransform3x4buffer)
2756                         permutation |= SHADERPERMUTATION_SKELETAL;
2757                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2758 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2759                 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);
2760 #endif
2761                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2762                 if (mode == SHADERMODE_LIGHTSOURCE)
2763                 {
2764                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2765                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2766                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2767                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2768                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2769                         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);
2770         
2771                         // additive passes are only darkened by fog, not tinted
2772                         if (r_glsl_permutation->loc_FogColor >= 0)
2773                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2774                         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);
2775                 }
2776                 else
2777                 {
2778                         if (mode == SHADERMODE_FLATCOLOR)
2779                         {
2780                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2781                         }
2782                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2783                         {
2784                                 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]);
2785                                 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]);
2786                                 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);
2787                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2788                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2789                                 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]);
2790                                 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]);
2791                         }
2792                         else
2793                         {
2794                                 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]);
2795                                 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]);
2796                                 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);
2797                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2798                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2799                         }
2800                         // additive passes are only darkened by fog, not tinted
2801                         if (r_glsl_permutation->loc_FogColor >= 0)
2802                         {
2803                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2804                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2805                                 else
2806                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2807                         }
2808                         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);
2809                         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]);
2810                         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]);
2811                         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]);
2812                         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]);
2813                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2814                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2815                         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);
2816                         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]);
2817                 }
2818                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2819                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2820                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2821                 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]);
2822                 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]);
2823
2824                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2825                 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));
2826                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2827                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2828                 {
2829                         if (rsurface.texture->pantstexture)
2830                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2831                         else
2832                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2833                 }
2834                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2835                 {
2836                         if (rsurface.texture->shirttexture)
2837                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2838                         else
2839                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2840                 }
2841                 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]);
2842                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2843                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2844                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2845                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2846                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2847                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2848                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2849                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2850                         );
2851                 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);
2852                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2853                 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]);
2854                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2855                 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);}
2856                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2857
2858                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2859                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2860                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2861                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2862                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2863                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2864                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2865                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2866                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2867                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2868                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2869                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2870                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2871                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2872                 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);
2873                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2874                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2875                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2876                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2877                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2878                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2879                 {
2880                         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);
2881                         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);
2882                         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);
2883                 }
2884                 else
2885                 {
2886                         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);
2887                 }
2888                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2889                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2890                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2891                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2892                 {
2893                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2894                         if (rsurface.rtlight)
2895                         {
2896                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2897                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2898                         }
2899                 }
2900                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2901                 CHECKGLERROR
2902                 break;
2903         case RENDERPATH_GL11:
2904         case RENDERPATH_GL13:
2905         case RENDERPATH_GLES1:
2906                 break;
2907         case RENDERPATH_SOFT:
2908                 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);
2909                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2910                 R_SetupShader_SetPermutationSoft(mode, permutation);
2911                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2912                 if (mode == SHADERMODE_LIGHTSOURCE)
2913                 {
2914                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2915                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2916                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2917                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2918                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2919                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2920         
2921                         // additive passes are only darkened by fog, not tinted
2922                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2923                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2924                 }
2925                 else
2926                 {
2927                         if (mode == SHADERMODE_FLATCOLOR)
2928                         {
2929                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2930                         }
2931                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2932                         {
2933                                 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]);
2934                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2935                                 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);
2936                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2937                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2938                                 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]);
2939                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2940                         }
2941                         else
2942                         {
2943                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2944                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2945                                 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);
2946                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2947                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2948                         }
2949                         // additive passes are only darkened by fog, not tinted
2950                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2951                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2952                         else
2953                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2954                         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);
2955                         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]);
2956                         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]);
2957                         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]);
2958                         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]);
2959                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2960                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2961                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2962                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2963                 }
2964                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2965                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2966                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2967                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2968                 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]);
2969
2970                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2971                 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));
2972                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2973                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2974                 {
2975                         if (rsurface.texture->pantstexture)
2976                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2977                         else
2978                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2979                 }
2980                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2981                 {
2982                         if (rsurface.texture->shirttexture)
2983                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2984                         else
2985                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2986                 }
2987                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2988                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2989                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2990                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2991                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2992                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2993                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2994                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2995                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2996                         );
2997                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2998                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2999                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3000                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3001
3002                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3003                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3004                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3005                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3006                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3007                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3008                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3009                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3010                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3011                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3012                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3013                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3014                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3015                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3016                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3017                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3018                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3019                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3020                 {
3021                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3022                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3023                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3024                 }
3025                 else
3026                 {
3027                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3028                 }
3029 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3030                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3031                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3032                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3033                 {
3034                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3035                         if (rsurface.rtlight)
3036                         {
3037                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3038                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3039                         }
3040                 }
3041                 break;
3042         }
3043 }
3044
3045 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3046 {
3047         // select a permutation of the lighting shader appropriate to this
3048         // combination of texture, entity, light source, and fogging, only use the
3049         // minimum features necessary to avoid wasting rendering time in the
3050         // fragment shader on features that are not being used
3051         unsigned int permutation = 0;
3052         unsigned int mode = 0;
3053         const float *lightcolorbase = rtlight->currentcolor;
3054         float ambientscale = rtlight->ambientscale;
3055         float diffusescale = rtlight->diffusescale;
3056         float specularscale = rtlight->specularscale;
3057         // this is the location of the light in view space
3058         vec3_t viewlightorigin;
3059         // this transforms from view space (camera) to light space (cubemap)
3060         matrix4x4_t viewtolight;
3061         matrix4x4_t lighttoview;
3062         float viewtolight16f[16];
3063         // light source
3064         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3065         if (rtlight->currentcubemap != r_texture_whitecube)
3066                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3067         if (diffusescale > 0)
3068                 permutation |= SHADERPERMUTATION_DIFFUSE;
3069         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3070                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3071         if (r_shadow_usingshadowmap2d)
3072         {
3073                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3074                 if (r_shadow_shadowmapvsdct)
3075                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3076
3077                 if (r_shadow_shadowmap2ddepthbuffer)
3078                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3079         }
3080         if (vid.allowalphatocoverage)
3081                 GL_AlphaToCoverage(false);
3082         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3083         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3084         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3085         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3086         switch(vid.renderpath)
3087         {
3088         case RENDERPATH_D3D9:
3089 #ifdef SUPPORTD3D
3090                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3091                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3092                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3093                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3094                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3095                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3096                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3097                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3098                 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);
3099                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3100                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3101
3102                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3103                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3104                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3105                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3106                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3107 #endif
3108                 break;
3109         case RENDERPATH_D3D10:
3110                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3111                 break;
3112         case RENDERPATH_D3D11:
3113                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3114                 break;
3115         case RENDERPATH_GL20:
3116         case RENDERPATH_GLES2:
3117                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3118                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3119                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3120                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3121                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3122                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3123                 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]);
3124                 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]);
3125                 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);
3126                 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]);
3127                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3128
3129                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3130                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3131                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3132                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3133                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3134                 break;
3135         case RENDERPATH_GL11:
3136         case RENDERPATH_GL13:
3137         case RENDERPATH_GLES1:
3138                 break;
3139         case RENDERPATH_SOFT:
3140                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3141                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3142                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3143                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3144                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3145                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3146                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3147                 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]);
3148                 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);
3149                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3150                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3151
3152                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3153                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3154                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3155                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3156                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3157                 break;
3158         }
3159 }
3160
3161 #define SKINFRAME_HASH 1024
3162
3163 typedef struct
3164 {
3165         int loadsequence; // incremented each level change
3166         memexpandablearray_t array;
3167         skinframe_t *hash[SKINFRAME_HASH];
3168 }
3169 r_skinframe_t;
3170 r_skinframe_t r_skinframe;
3171
3172 void R_SkinFrame_PrepareForPurge(void)
3173 {
3174         r_skinframe.loadsequence++;
3175         // wrap it without hitting zero
3176         if (r_skinframe.loadsequence >= 200)
3177                 r_skinframe.loadsequence = 1;
3178 }
3179
3180 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3181 {
3182         if (!skinframe)
3183                 return;
3184         // mark the skinframe as used for the purging code
3185         skinframe->loadsequence = r_skinframe.loadsequence;
3186 }
3187
3188 void R_SkinFrame_Purge(void)
3189 {
3190         int i;
3191         skinframe_t *s;
3192         for (i = 0;i < SKINFRAME_HASH;i++)
3193         {
3194                 for (s = r_skinframe.hash[i];s;s = s->next)
3195                 {
3196                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3197                         {
3198                                 if (s->merged == s->base)
3199                                         s->merged = NULL;
3200                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3201                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3202                                 R_PurgeTexture(s->merged);s->merged = NULL;
3203                                 R_PurgeTexture(s->base  );s->base   = NULL;
3204                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3205                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3206                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3207                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3208                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3209                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3210                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3211                                 s->loadsequence = 0;
3212                         }
3213                 }
3214         }
3215 }
3216
3217 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3218         skinframe_t *item;
3219         char basename[MAX_QPATH];
3220
3221         Image_StripImageExtension(name, basename, sizeof(basename));
3222
3223         if( last == NULL ) {
3224                 int hashindex;
3225                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3226                 item = r_skinframe.hash[hashindex];
3227         } else {
3228                 item = last->next;
3229         }
3230
3231         // linearly search through the hash bucket
3232         for( ; item ; item = item->next ) {
3233                 if( !strcmp( item->basename, basename ) ) {
3234                         return item;
3235                 }
3236         }
3237         return NULL;
3238 }
3239
3240 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3241 {
3242         skinframe_t *item;
3243         int hashindex;
3244         char basename[MAX_QPATH];
3245
3246         Image_StripImageExtension(name, basename, sizeof(basename));
3247
3248         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3249         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3250                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3251                         break;
3252
3253         if (!item) {
3254                 rtexture_t *dyntexture;
3255                 // check whether its a dynamic texture
3256                 dyntexture = CL_GetDynTexture( basename );
3257                 if (!add && !dyntexture)
3258                         return NULL;
3259                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3260                 memset(item, 0, sizeof(*item));
3261                 strlcpy(item->basename, basename, sizeof(item->basename));
3262                 item->base = dyntexture; // either NULL or dyntexture handle
3263                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3264                 item->comparewidth = comparewidth;
3265                 item->compareheight = compareheight;
3266                 item->comparecrc = comparecrc;
3267                 item->next = r_skinframe.hash[hashindex];
3268                 r_skinframe.hash[hashindex] = item;
3269         }
3270         else if (textureflags & TEXF_FORCE_RELOAD)
3271         {
3272                 rtexture_t *dyntexture;
3273                 // check whether its a dynamic texture
3274                 dyntexture = CL_GetDynTexture( basename );
3275                 if (!add && !dyntexture)
3276                         return NULL;
3277                 if (item->merged == item->base)
3278                         item->merged = NULL;
3279                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3280                 R_PurgeTexture(item->stain );item->stain  = NULL;
3281                 R_PurgeTexture(item->merged);item->merged = NULL;
3282                 R_PurgeTexture(item->base  );item->base   = NULL;
3283                 R_PurgeTexture(item->pants );item->pants  = NULL;
3284                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3285                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3286                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3287                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3288                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3289         R_PurgeTexture(item->reflect);item->reflect = NULL;
3290                 item->loadsequence = 0;
3291         }
3292         else if( item->base == NULL )
3293         {
3294                 rtexture_t *dyntexture;
3295                 // check whether its a dynamic texture
3296                 // 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]
3297                 dyntexture = CL_GetDynTexture( basename );
3298                 item->base = dyntexture; // either NULL or dyntexture handle
3299         }
3300
3301         R_SkinFrame_MarkUsed(item);
3302         return item;
3303 }
3304
3305 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3306         { \
3307                 unsigned long long avgcolor[5], wsum; \
3308                 int pix, comp, w; \
3309                 avgcolor[0] = 0; \
3310                 avgcolor[1] = 0; \
3311                 avgcolor[2] = 0; \
3312                 avgcolor[3] = 0; \
3313                 avgcolor[4] = 0; \
3314                 wsum = 0; \
3315                 for(pix = 0; pix < cnt; ++pix) \
3316                 { \
3317                         w = 0; \
3318                         for(comp = 0; comp < 3; ++comp) \
3319                                 w += getpixel; \
3320                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3321                         { \
3322                                 ++wsum; \
3323                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3324                                 w = getpixel; \
3325                                 for(comp = 0; comp < 3; ++comp) \
3326                                         avgcolor[comp] += getpixel * w; \
3327                                 avgcolor[3] += w; \
3328                         } \
3329                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3330                         avgcolor[4] += getpixel; \
3331                 } \
3332                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3333                         avgcolor[3] = 1; \
3334                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3335                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3336                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3337                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3338         }
3339
3340 extern cvar_t gl_picmip;
3341 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3342 {
3343         int j;
3344         unsigned char *pixels;
3345         unsigned char *bumppixels;
3346         unsigned char *basepixels = NULL;
3347         int basepixels_width = 0;
3348         int basepixels_height = 0;
3349         skinframe_t *skinframe;
3350         rtexture_t *ddsbase = NULL;
3351         qboolean ddshasalpha = false;
3352         float ddsavgcolor[4];
3353         char basename[MAX_QPATH];
3354         int miplevel = R_PicmipForFlags(textureflags);
3355         int savemiplevel = miplevel;
3356         int mymiplevel;
3357         char vabuf[1024];
3358
3359         if (cls.state == ca_dedicated)
3360                 return NULL;
3361
3362         // return an existing skinframe if already loaded
3363         // if loading of the first image fails, don't make a new skinframe as it
3364         // would cause all future lookups of this to be missing
3365         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3366         if (skinframe && skinframe->base)
3367                 return skinframe;
3368
3369         Image_StripImageExtension(name, basename, sizeof(basename));
3370
3371         // check for DDS texture file first
3372         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3373         {
3374                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3375                 if (basepixels == NULL)
3376                         return NULL;
3377         }
3378
3379         // FIXME handle miplevel
3380
3381         if (developer_loading.integer)
3382                 Con_Printf("loading skin \"%s\"\n", name);
3383
3384         // we've got some pixels to store, so really allocate this new texture now
3385         if (!skinframe)
3386                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3387         textureflags &= ~TEXF_FORCE_RELOAD;
3388         skinframe->stain = NULL;
3389         skinframe->merged = NULL;
3390         skinframe->base = NULL;
3391         skinframe->pants = NULL;
3392         skinframe->shirt = NULL;
3393         skinframe->nmap = NULL;
3394         skinframe->gloss = NULL;
3395         skinframe->glow = NULL;
3396         skinframe->fog = NULL;
3397         skinframe->reflect = NULL;
3398         skinframe->hasalpha = false;
3399
3400         if (ddsbase)
3401         {
3402                 skinframe->base = ddsbase;
3403                 skinframe->hasalpha = ddshasalpha;
3404                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3405                 if (r_loadfog && skinframe->hasalpha)
3406                         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);
3407                 //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]);
3408         }
3409         else
3410         {
3411                 basepixels_width = image_width;
3412                 basepixels_height = image_height;
3413                 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);
3414                 if (textureflags & TEXF_ALPHA)
3415                 {
3416                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3417                         {
3418                                 if (basepixels[j] < 255)
3419                                 {
3420                                         skinframe->hasalpha = true;
3421                                         break;
3422                                 }
3423                         }
3424                         if (r_loadfog && skinframe->hasalpha)
3425                         {
3426                                 // has transparent pixels
3427                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3428                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3429                                 {
3430                                         pixels[j+0] = 255;
3431                                         pixels[j+1] = 255;
3432                                         pixels[j+2] = 255;
3433                                         pixels[j+3] = basepixels[j+3];
3434                                 }
3435                                 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);
3436                                 Mem_Free(pixels);
3437                         }
3438                 }
3439                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3440 #ifndef USE_GLES2
3441                 //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]);
3442                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3443                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3444                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3445                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3446 #endif
3447         }
3448
3449         if (r_loaddds)
3450         {
3451                 mymiplevel = savemiplevel;
3452                 if (r_loadnormalmap)
3453                         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);
3454                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3455                 if (r_loadgloss)
3456                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3457                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3458                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3459                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3460         }
3461
3462         // _norm is the name used by tenebrae and has been adopted as standard
3463         if (r_loadnormalmap && skinframe->nmap == NULL)
3464         {
3465                 mymiplevel = savemiplevel;
3466                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3467                 {
3468                         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);
3469                         Mem_Free(pixels);
3470                         pixels = NULL;
3471                 }
3472                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3473                 {
3474                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3475                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3476                         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);
3477                         Mem_Free(pixels);
3478                         Mem_Free(bumppixels);
3479                 }
3480                 else if (r_shadow_bumpscale_basetexture.value > 0)
3481                 {
3482                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3483                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3484                         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);
3485                         Mem_Free(pixels);
3486                 }
3487 #ifndef USE_GLES2
3488                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3489                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3490 #endif
3491         }
3492
3493         // _luma is supported only for tenebrae compatibility
3494         // _glow is the preferred name
3495         mymiplevel = savemiplevel;
3496         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))))
3497         {
3498                 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);
3499 #ifndef USE_GLES2
3500                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3501                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3502 #endif
3503                 Mem_Free(pixels);pixels = NULL;
3504         }
3505
3506         mymiplevel = savemiplevel;
3507         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3508         {
3509                 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);
3510 #ifndef USE_GLES2
3511                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3512                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3513 #endif
3514                 Mem_Free(pixels);
3515                 pixels = NULL;
3516         }
3517
3518         mymiplevel = savemiplevel;
3519         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3520         {
3521                 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);
3522 #ifndef USE_GLES2
3523                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3524                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3525 #endif
3526                 Mem_Free(pixels);
3527                 pixels = NULL;
3528         }
3529
3530         mymiplevel = savemiplevel;
3531         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3532         {
3533                 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);
3534 #ifndef USE_GLES2
3535                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3536                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3537 #endif
3538                 Mem_Free(pixels);
3539                 pixels = NULL;
3540         }
3541
3542         mymiplevel = savemiplevel;
3543         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3544         {
3545                 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);
3546 #ifndef USE_GLES2
3547                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3548                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3549 #endif
3550                 Mem_Free(pixels);
3551                 pixels = NULL;
3552         }
3553
3554         if (basepixels)
3555                 Mem_Free(basepixels);
3556
3557         return skinframe;
3558 }
3559
3560 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3561 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3562 {
3563         int i;
3564         unsigned char *temp1, *temp2;
3565         skinframe_t *skinframe;
3566         char vabuf[1024];
3567
3568         if (cls.state == ca_dedicated)
3569                 return NULL;
3570
3571         // if already loaded just return it, otherwise make a new skinframe
3572         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3573         if (skinframe->base)
3574                 return skinframe;
3575         textureflags &= ~TEXF_FORCE_RELOAD;
3576
3577         skinframe->stain = NULL;
3578         skinframe->merged = NULL;
3579         skinframe->base = NULL;
3580         skinframe->pants = NULL;
3581         skinframe->shirt = NULL;
3582         skinframe->nmap = NULL;
3583         skinframe->gloss = NULL;
3584         skinframe->glow = NULL;
3585         skinframe->fog = NULL;
3586         skinframe->reflect = NULL;
3587         skinframe->hasalpha = false;
3588
3589         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3590         if (!skindata)
3591                 return NULL;
3592
3593         if (developer_loading.integer)
3594                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3595
3596         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3597         {
3598                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3599                 temp2 = temp1 + width * height * 4;
3600                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3601                 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);
3602                 Mem_Free(temp1);
3603         }
3604         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3605         if (textureflags & TEXF_ALPHA)
3606         {
3607                 for (i = 3;i < width * height * 4;i += 4)
3608                 {
3609                         if (skindata[i] < 255)
3610                         {
3611                                 skinframe->hasalpha = true;
3612                                 break;
3613                         }
3614                 }
3615                 if (r_loadfog && skinframe->hasalpha)
3616                 {
3617                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3618                         memcpy(fogpixels, skindata, width * height * 4);
3619                         for (i = 0;i < width * height * 4;i += 4)
3620                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3621                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3622                         Mem_Free(fogpixels);
3623                 }
3624         }
3625
3626         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3627         //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]);
3628
3629         return skinframe;
3630 }
3631
3632 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3633 {
3634         int i;
3635         int featuresmask;
3636         skinframe_t *skinframe;
3637
3638         if (cls.state == ca_dedicated)
3639                 return NULL;
3640
3641         // if already loaded just return it, otherwise make a new skinframe
3642         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3643         if (skinframe->base)
3644                 return skinframe;
3645         //textureflags &= ~TEXF_FORCE_RELOAD;
3646
3647         skinframe->stain = NULL;
3648         skinframe->merged = NULL;
3649         skinframe->base = NULL;
3650         skinframe->pants = NULL;
3651         skinframe->shirt = NULL;
3652         skinframe->nmap = NULL;
3653         skinframe->gloss = NULL;
3654         skinframe->glow = NULL;
3655         skinframe->fog = NULL;
3656         skinframe->reflect = NULL;
3657         skinframe->hasalpha = false;
3658
3659         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3660         if (!skindata)
3661                 return NULL;
3662
3663         if (developer_loading.integer)
3664                 Con_Printf("loading quake skin \"%s\"\n", name);
3665
3666         // 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)
3667         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3668         memcpy(skinframe->qpixels, skindata, width*height);
3669         skinframe->qwidth = width;
3670         skinframe->qheight = height;
3671
3672         featuresmask = 0;
3673         for (i = 0;i < width * height;i++)
3674                 featuresmask |= palette_featureflags[skindata[i]];
3675
3676         skinframe->hasalpha = false;
3677         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3678         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3679         skinframe->qgeneratemerged = true;
3680         skinframe->qgeneratebase = skinframe->qhascolormapping;
3681         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3682
3683         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3684         //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]);
3685
3686         return skinframe;
3687 }
3688
3689 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3690 {
3691         int width;
3692         int height;
3693         unsigned char *skindata;
3694         char vabuf[1024];
3695
3696         if (!skinframe->qpixels)
3697                 return;
3698
3699         if (!skinframe->qhascolormapping)
3700                 colormapped = false;
3701
3702         if (colormapped)
3703         {
3704                 if (!skinframe->qgeneratebase)
3705                         return;
3706         }
3707         else
3708         {
3709                 if (!skinframe->qgeneratemerged)
3710                         return;
3711         }
3712
3713         width = skinframe->qwidth;
3714         height = skinframe->qheight;
3715         skindata = skinframe->qpixels;
3716
3717         if (skinframe->qgeneratenmap)
3718         {
3719                 unsigned char *temp1, *temp2;
3720                 skinframe->qgeneratenmap = false;
3721                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3722                 temp2 = temp1 + width * height * 4;
3723                 // use either a custom palette or the quake palette
3724                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3725                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3726                 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);
3727                 Mem_Free(temp1);
3728         }
3729
3730         if (skinframe->qgenerateglow)
3731         {
3732                 skinframe->qgenerateglow = false;
3733                 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
3734         }
3735
3736         if (colormapped)
3737         {
3738                 skinframe->qgeneratebase = false;
3739                 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);
3740                 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);
3741                 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);
3742         }
3743         else
3744         {
3745                 skinframe->qgeneratemerged = false;
3746                 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);
3747         }
3748
3749         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3750         {
3751                 Mem_Free(skinframe->qpixels);
3752                 skinframe->qpixels = NULL;
3753         }
3754 }
3755
3756 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)
3757 {
3758         int i;
3759         skinframe_t *skinframe;
3760         char vabuf[1024];
3761
3762         if (cls.state == ca_dedicated)
3763                 return NULL;
3764
3765         // if already loaded just return it, otherwise make a new skinframe
3766         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3767         if (skinframe->base)
3768                 return skinframe;
3769         textureflags &= ~TEXF_FORCE_RELOAD;
3770
3771         skinframe->stain = NULL;
3772         skinframe->merged = NULL;
3773         skinframe->base = NULL;
3774         skinframe->pants = NULL;
3775         skinframe->shirt = NULL;
3776         skinframe->nmap = NULL;
3777         skinframe->gloss = NULL;
3778         skinframe->glow = NULL;
3779         skinframe->fog = NULL;
3780         skinframe->reflect = NULL;
3781         skinframe->hasalpha = false;
3782
3783         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3784         if (!skindata)
3785                 return NULL;
3786
3787         if (developer_loading.integer)
3788                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3789
3790         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3791         if (textureflags & TEXF_ALPHA)
3792         {
3793                 for (i = 0;i < width * height;i++)
3794                 {
3795                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3796                         {
3797                                 skinframe->hasalpha = true;
3798                                 break;
3799                         }
3800                 }
3801                 if (r_loadfog && skinframe->hasalpha)
3802                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3803         }
3804
3805         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3806         //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]);
3807
3808         return skinframe;
3809 }
3810
3811 skinframe_t *R_SkinFrame_LoadMissing(void)
3812 {
3813         skinframe_t *skinframe;
3814
3815         if (cls.state == ca_dedicated)
3816                 return NULL;
3817
3818         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3819         skinframe->stain = NULL;
3820         skinframe->merged = NULL;
3821         skinframe->base = NULL;
3822         skinframe->pants = NULL;
3823         skinframe->shirt = NULL;
3824         skinframe->nmap = NULL;
3825         skinframe->gloss = NULL;
3826         skinframe->glow = NULL;
3827         skinframe->fog = NULL;
3828         skinframe->reflect = NULL;
3829         skinframe->hasalpha = false;
3830
3831         skinframe->avgcolor[0] = rand() / RAND_MAX;
3832         skinframe->avgcolor[1] = rand() / RAND_MAX;
3833         skinframe->avgcolor[2] = rand() / RAND_MAX;
3834         skinframe->avgcolor[3] = 1;
3835
3836         return skinframe;
3837 }
3838
3839 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3840 typedef struct suffixinfo_s
3841 {
3842         const char *suffix;
3843         qboolean flipx, flipy, flipdiagonal;
3844 }
3845 suffixinfo_t;
3846 static suffixinfo_t suffix[3][6] =
3847 {
3848         {
3849                 {"px",   false, false, false},
3850                 {"nx",   false, false, false},
3851                 {"py",   false, false, false},
3852                 {"ny",   false, false, false},
3853                 {"pz",   false, false, false},
3854                 {"nz",   false, false, false}
3855         },
3856         {
3857                 {"posx", false, false, false},
3858                 {"negx", false, false, false},
3859                 {"posy", false, false, false},
3860                 {"negy", false, false, false},
3861                 {"posz", false, false, false},
3862                 {"negz", false, false, false}
3863         },
3864         {
3865                 {"rt",    true, false,  true},
3866                 {"lf",   false,  true,  true},
3867                 {"ft",    true,  true, false},
3868                 {"bk",   false, false, false},
3869                 {"up",    true, false,  true},
3870                 {"dn",    true, false,  true}
3871         }
3872 };
3873
3874 static int componentorder[4] = {0, 1, 2, 3};
3875
3876 static rtexture_t *R_LoadCubemap(const char *basename)
3877 {
3878         int i, j, cubemapsize;
3879         unsigned char *cubemappixels, *image_buffer;
3880         rtexture_t *cubemaptexture;
3881         char name[256];
3882         // must start 0 so the first loadimagepixels has no requested width/height
3883         cubemapsize = 0;
3884         cubemappixels = NULL;
3885         cubemaptexture = NULL;
3886         // keep trying different suffix groups (posx, px, rt) until one loads
3887         for (j = 0;j < 3 && !cubemappixels;j++)
3888         {
3889                 // load the 6 images in the suffix group
3890                 for (i = 0;i < 6;i++)
3891                 {
3892                         // generate an image name based on the base and and suffix
3893                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3894                         // load it
3895                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3896                         {
3897                                 // an image loaded, make sure width and height are equal
3898                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3899                                 {
3900                                         // if this is the first image to load successfully, allocate the cubemap memory
3901                                         if (!cubemappixels && image_width >= 1)
3902                                         {
3903                                                 cubemapsize = image_width;
3904                                                 // note this clears to black, so unavailable sides are black
3905                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3906                                         }
3907                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3908                                         if (cubemappixels)
3909                                                 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);
3910                                 }
3911                                 else
3912                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3913                                 // free the image
3914                                 Mem_Free(image_buffer);
3915                         }
3916                 }
3917         }
3918         // if a cubemap loaded, upload it
3919         if (cubemappixels)
3920         {
3921                 if (developer_loading.integer)
3922                         Con_Printf("loading cubemap \"%s\"\n", basename);
3923
3924                 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);
3925                 Mem_Free(cubemappixels);
3926         }
3927         else
3928         {
3929                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3930                 if (developer_loading.integer)
3931                 {
3932                         Con_Printf("(tried tried images ");
3933                         for (j = 0;j < 3;j++)
3934                                 for (i = 0;i < 6;i++)
3935                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3936                         Con_Print(" and was unable to find any of them).\n");
3937                 }
3938         }
3939         return cubemaptexture;
3940 }
3941
3942 rtexture_t *R_GetCubemap(const char *basename)
3943 {
3944         int i;
3945         for (i = 0;i < r_texture_numcubemaps;i++)
3946                 if (r_texture_cubemaps[i] != NULL)
3947                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3948                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3949         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3950                 return r_texture_whitecube;
3951         r_texture_numcubemaps++;
3952         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3953         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3954         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3955         return r_texture_cubemaps[i]->texture;
3956 }
3957
3958 static void R_Main_FreeViewCache(void)
3959 {
3960         if (r_refdef.viewcache.entityvisible)
3961                 Mem_Free(r_refdef.viewcache.entityvisible);
3962         if (r_refdef.viewcache.world_pvsbits)
3963                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3964         if (r_refdef.viewcache.world_leafvisible)
3965                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3966         if (r_refdef.viewcache.world_surfacevisible)
3967                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3968         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3969 }
3970
3971 static void R_Main_ResizeViewCache(void)
3972 {
3973         int numentities = r_refdef.scene.numentities;
3974         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3975         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3976         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3977         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3978         if (r_refdef.viewcache.maxentities < numentities)
3979         {
3980                 r_refdef.viewcache.maxentities = numentities;
3981                 if (r_refdef.viewcache.entityvisible)
3982                         Mem_Free(r_refdef.viewcache.entityvisible);
3983                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3984         }
3985         if (r_refdef.viewcache.world_numclusters != numclusters)
3986         {
3987                 r_refdef.viewcache.world_numclusters = numclusters;
3988                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3989                 if (r_refdef.viewcache.world_pvsbits)
3990                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3991                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3992         }
3993         if (r_refdef.viewcache.world_numleafs != numleafs)
3994         {
3995                 r_refdef.viewcache.world_numleafs = numleafs;
3996                 if (r_refdef.viewcache.world_leafvisible)
3997                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3998                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3999         }
4000         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4001         {
4002                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4003                 if (r_refdef.viewcache.world_surfacevisible)
4004                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4005                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4006         }
4007 }
4008
4009 extern rtexture_t *loadingscreentexture;
4010 static void gl_main_start(void)
4011 {
4012         loadingscreentexture = NULL;
4013         r_texture_blanknormalmap = NULL;
4014         r_texture_white = NULL;
4015         r_texture_grey128 = NULL;
4016         r_texture_black = NULL;
4017         r_texture_whitecube = NULL;
4018         r_texture_normalizationcube = NULL;
4019         r_texture_fogattenuation = NULL;
4020         r_texture_fogheighttexture = NULL;
4021         r_texture_gammaramps = NULL;
4022         r_texture_numcubemaps = 0;
4023         r_uniformbufferalignment = 32;
4024
4025         r_loaddds = r_texture_dds_load.integer != 0;
4026         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4027
4028         switch(vid.renderpath)
4029         {
4030         case RENDERPATH_GL20:
4031         case RENDERPATH_D3D9:
4032         case RENDERPATH_D3D10:
4033         case RENDERPATH_D3D11:
4034         case RENDERPATH_SOFT:
4035         case RENDERPATH_GLES2:
4036                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4037                 Cvar_SetValueQuick(&gl_combine, 1);
4038                 Cvar_SetValueQuick(&r_glsl, 1);
4039                 r_loadnormalmap = true;
4040                 r_loadgloss = true;
4041                 r_loadfog = false;
4042 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4043                 if (vid.support.arb_uniform_buffer_object)
4044                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4045 #endif
4046                         break;
4047         case RENDERPATH_GL13:
4048         case RENDERPATH_GLES1:
4049                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4050                 Cvar_SetValueQuick(&gl_combine, 1);
4051                 Cvar_SetValueQuick(&r_glsl, 0);
4052                 r_loadnormalmap = false;
4053                 r_loadgloss = false;
4054                 r_loadfog = true;
4055                 break;
4056         case RENDERPATH_GL11:
4057                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4058                 Cvar_SetValueQuick(&gl_combine, 0);
4059                 Cvar_SetValueQuick(&r_glsl, 0);
4060                 r_loadnormalmap = false;
4061                 r_loadgloss = false;
4062                 r_loadfog = true;
4063                 break;
4064         }
4065
4066         R_AnimCache_Free();
4067         R_FrameData_Reset();
4068         R_BufferData_Reset();
4069
4070         r_numqueries = 0;
4071         r_maxqueries = 0;
4072         memset(r_queries, 0, sizeof(r_queries));
4073
4074         r_qwskincache = NULL;
4075         r_qwskincache_size = 0;
4076
4077         // due to caching of texture_t references, the collision cache must be reset
4078         Collision_Cache_Reset(true);
4079
4080         // set up r_skinframe loading system for textures
4081         memset(&r_skinframe, 0, sizeof(r_skinframe));
4082         r_skinframe.loadsequence = 1;
4083         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4084
4085         r_main_texturepool = R_AllocTexturePool();
4086         R_BuildBlankTextures();
4087         R_BuildNoTexture();
4088         if (vid.support.arb_texture_cube_map)
4089         {
4090                 R_BuildWhiteCube();
4091                 R_BuildNormalizationCube();
4092         }
4093         r_texture_fogattenuation = NULL;
4094         r_texture_fogheighttexture = NULL;
4095         r_texture_gammaramps = NULL;
4096         //r_texture_fogintensity = NULL;
4097         memset(&r_fb, 0, sizeof(r_fb));
4098         r_glsl_permutation = NULL;
4099         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4100         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4101         glslshaderstring = NULL;
4102 #ifdef SUPPORTD3D
4103         r_hlsl_permutation = NULL;
4104         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4105         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4106 #endif
4107         hlslshaderstring = NULL;
4108         memset(&r_svbsp, 0, sizeof (r_svbsp));
4109
4110         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4111         r_texture_numcubemaps = 0;
4112
4113         r_refdef.fogmasktable_density = 0;
4114
4115 #ifdef __ANDROID__
4116         // For Steelstorm Android
4117         // FIXME CACHE the program and reload
4118         // FIXME see possible combinations for SS:BR android
4119         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4120         R_SetupShader_SetPermutationGLSL(0, 12);
4121         R_SetupShader_SetPermutationGLSL(0, 13);
4122         R_SetupShader_SetPermutationGLSL(0, 8388621);
4123         R_SetupShader_SetPermutationGLSL(3, 0);
4124         R_SetupShader_SetPermutationGLSL(3, 2048);
4125         R_SetupShader_SetPermutationGLSL(5, 0);
4126         R_SetupShader_SetPermutationGLSL(5, 2);
4127         R_SetupShader_SetPermutationGLSL(5, 2048);
4128         R_SetupShader_SetPermutationGLSL(5, 8388608);
4129         R_SetupShader_SetPermutationGLSL(11, 1);
4130         R_SetupShader_SetPermutationGLSL(11, 2049);
4131         R_SetupShader_SetPermutationGLSL(11, 8193);
4132         R_SetupShader_SetPermutationGLSL(11, 10241);
4133         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4134 #endif
4135 }
4136
4137 static void gl_main_shutdown(void)
4138 {
4139         R_AnimCache_Free();
4140         R_FrameData_Reset();
4141         R_BufferData_Reset();
4142
4143         R_Main_FreeViewCache();
4144
4145         switch(vid.renderpath)
4146         {
4147         case RENDERPATH_GL11:
4148         case RENDERPATH_GL13:
4149         case RENDERPATH_GL20:
4150         case RENDERPATH_GLES1:
4151         case RENDERPATH_GLES2:
4152 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4153                 if (r_maxqueries)
4154                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4155 #endif
4156                 break;
4157         case RENDERPATH_D3D9:
4158                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4159                 break;
4160         case RENDERPATH_D3D10:
4161                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4162                 break;
4163         case RENDERPATH_D3D11:
4164                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4165                 break;
4166         case RENDERPATH_SOFT:
4167                 break;
4168         }
4169
4170         r_numqueries = 0;
4171         r_maxqueries = 0;
4172         memset(r_queries, 0, sizeof(r_queries));
4173
4174         r_qwskincache = NULL;
4175         r_qwskincache_size = 0;
4176
4177         // clear out the r_skinframe state
4178         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4179         memset(&r_skinframe, 0, sizeof(r_skinframe));
4180
4181         if (r_svbsp.nodes)
4182                 Mem_Free(r_svbsp.nodes);
4183         memset(&r_svbsp, 0, sizeof (r_svbsp));
4184         R_FreeTexturePool(&r_main_texturepool);
4185         loadingscreentexture = NULL;
4186         r_texture_blanknormalmap = NULL;
4187         r_texture_white = NULL;
4188         r_texture_grey128 = NULL;
4189         r_texture_black = NULL;
4190         r_texture_whitecube = NULL;
4191         r_texture_normalizationcube = NULL;
4192         r_texture_fogattenuation = NULL;
4193         r_texture_fogheighttexture = NULL;
4194         r_texture_gammaramps = NULL;
4195         r_texture_numcubemaps = 0;
4196         //r_texture_fogintensity = NULL;
4197         memset(&r_fb, 0, sizeof(r_fb));
4198         R_GLSL_Restart_f();
4199
4200         r_glsl_permutation = NULL;
4201         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4202         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4203         glslshaderstring = NULL;
4204 #ifdef SUPPORTD3D
4205         r_hlsl_permutation = NULL;
4206         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4207         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4208 #endif
4209         hlslshaderstring = NULL;
4210 }
4211
4212 static void gl_main_newmap(void)
4213 {
4214         // FIXME: move this code to client
4215         char *entities, entname[MAX_QPATH];
4216         if (r_qwskincache)
4217                 Mem_Free(r_qwskincache);
4218         r_qwskincache = NULL;
4219         r_qwskincache_size = 0;
4220         if (cl.worldmodel)
4221         {
4222                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4223                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4224                 {
4225                         CL_ParseEntityLump(entities);
4226                         Mem_Free(entities);
4227                         return;
4228                 }
4229                 if (cl.worldmodel->brush.entities)
4230                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4231         }
4232         R_Main_FreeViewCache();
4233
4234         R_FrameData_Reset();
4235         R_BufferData_Reset();
4236 }
4237
4238 void GL_Main_Init(void)
4239 {
4240         int i;
4241         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4242
4243         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4244         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4245         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4246         if (gamemode == GAME_NEHAHRA)
4247         {
4248                 Cvar_RegisterVariable (&gl_fogenable);
4249                 Cvar_RegisterVariable (&gl_fogdensity);
4250                 Cvar_RegisterVariable (&gl_fogred);
4251                 Cvar_RegisterVariable (&gl_foggreen);
4252                 Cvar_RegisterVariable (&gl_fogblue);
4253                 Cvar_RegisterVariable (&gl_fogstart);
4254                 Cvar_RegisterVariable (&gl_fogend);
4255                 Cvar_RegisterVariable (&gl_skyclip);
4256         }
4257         Cvar_RegisterVariable(&r_motionblur);
4258         Cvar_RegisterVariable(&r_damageblur);
4259         Cvar_RegisterVariable(&r_motionblur_averaging);
4260         Cvar_RegisterVariable(&r_motionblur_randomize);
4261         Cvar_RegisterVariable(&r_motionblur_minblur);
4262         Cvar_RegisterVariable(&r_motionblur_maxblur);
4263         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4264         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4265         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4266         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4267         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4268         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4269         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4270         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4271         Cvar_RegisterVariable(&r_equalize_entities_by);
4272         Cvar_RegisterVariable(&r_equalize_entities_to);
4273         Cvar_RegisterVariable(&r_depthfirst);
4274         Cvar_RegisterVariable(&r_useinfinitefarclip);
4275         Cvar_RegisterVariable(&r_farclip_base);
4276         Cvar_RegisterVariable(&r_farclip_world);
4277         Cvar_RegisterVariable(&r_nearclip);
4278         Cvar_RegisterVariable(&r_deformvertexes);
4279         Cvar_RegisterVariable(&r_transparent);
4280         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4281         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4282         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4283         Cvar_RegisterVariable(&r_showoverdraw);
4284         Cvar_RegisterVariable(&r_showbboxes);
4285         Cvar_RegisterVariable(&r_showsurfaces);
4286         Cvar_RegisterVariable(&r_showtris);
4287         Cvar_RegisterVariable(&r_shownormals);
4288         Cvar_RegisterVariable(&r_showlighting);
4289         Cvar_RegisterVariable(&r_showshadowvolumes);
4290         Cvar_RegisterVariable(&r_showcollisionbrushes);
4291         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4292         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4293         Cvar_RegisterVariable(&r_showdisabledepthtest);
4294         Cvar_RegisterVariable(&r_drawportals);
4295         Cvar_RegisterVariable(&r_drawentities);
4296         Cvar_RegisterVariable(&r_draw2d);
4297         Cvar_RegisterVariable(&r_drawworld);
4298         Cvar_RegisterVariable(&r_cullentities_trace);
4299         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4300         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4301         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4302         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4303         Cvar_RegisterVariable(&r_sortentities);
4304         Cvar_RegisterVariable(&r_drawviewmodel);
4305         Cvar_RegisterVariable(&r_drawexteriormodel);
4306         Cvar_RegisterVariable(&r_speeds);
4307         Cvar_RegisterVariable(&r_fullbrights);
4308         Cvar_RegisterVariable(&r_wateralpha);
4309         Cvar_RegisterVariable(&r_dynamic);
4310         Cvar_RegisterVariable(&r_fakelight);
4311         Cvar_RegisterVariable(&r_fakelight_intensity);
4312         Cvar_RegisterVariable(&r_fullbright);
4313         Cvar_RegisterVariable(&r_shadows);
4314         Cvar_RegisterVariable(&r_shadows_darken);
4315         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4316         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4317         Cvar_RegisterVariable(&r_shadows_throwdistance);
4318         Cvar_RegisterVariable(&r_shadows_throwdirection);
4319         Cvar_RegisterVariable(&r_shadows_focus);
4320         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4321         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4322         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4323         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4324         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4325         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4326         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4327         Cvar_RegisterVariable(&r_fog_exp2);
4328         Cvar_RegisterVariable(&r_fog_clear);
4329         Cvar_RegisterVariable(&r_drawfog);
4330         Cvar_RegisterVariable(&r_transparentdepthmasking);
4331         Cvar_RegisterVariable(&r_transparent_sortmindist);
4332         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4333         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4334         Cvar_RegisterVariable(&r_texture_dds_load);
4335         Cvar_RegisterVariable(&r_texture_dds_save);
4336         Cvar_RegisterVariable(&r_textureunits);
4337         Cvar_RegisterVariable(&gl_combine);
4338         Cvar_RegisterVariable(&r_usedepthtextures);
4339         Cvar_RegisterVariable(&r_viewfbo);
4340         Cvar_RegisterVariable(&r_viewscale);
4341         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4342         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4343         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4344         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4345         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4346         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4347         Cvar_RegisterVariable(&r_glsl);
4348         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4349         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4350         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4351         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4352         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4353         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4354         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4355         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4356         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4357         Cvar_RegisterVariable(&r_glsl_postprocess);
4358         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4359         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4360         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4361         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4362         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4363         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4364         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4365         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4366         Cvar_RegisterVariable(&r_celshading);
4367         Cvar_RegisterVariable(&r_celoutlines);
4368
4369         Cvar_RegisterVariable(&r_water);
4370         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4371         Cvar_RegisterVariable(&r_water_clippingplanebias);
4372         Cvar_RegisterVariable(&r_water_refractdistort);
4373         Cvar_RegisterVariable(&r_water_reflectdistort);
4374         Cvar_RegisterVariable(&r_water_scissormode);
4375         Cvar_RegisterVariable(&r_water_lowquality);
4376         Cvar_RegisterVariable(&r_water_hideplayer);
4377         Cvar_RegisterVariable(&r_water_fbo);
4378
4379         Cvar_RegisterVariable(&r_lerpsprites);
4380         Cvar_RegisterVariable(&r_lerpmodels);
4381         Cvar_RegisterVariable(&r_lerplightstyles);
4382         Cvar_RegisterVariable(&r_waterscroll);
4383         Cvar_RegisterVariable(&r_bloom);
4384         Cvar_RegisterVariable(&r_bloom_colorscale);
4385         Cvar_RegisterVariable(&r_bloom_brighten);
4386         Cvar_RegisterVariable(&r_bloom_blur);
4387         Cvar_RegisterVariable(&r_bloom_resolution);
4388         Cvar_RegisterVariable(&r_bloom_colorexponent);
4389         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4390         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4391         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4392         Cvar_RegisterVariable(&r_hdr_glowintensity);
4393         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4394         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4395         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4396         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4397         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4398         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4399         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4400         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4401         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4402         Cvar_RegisterVariable(&developer_texturelogging);
4403         Cvar_RegisterVariable(&gl_lightmaps);
4404         Cvar_RegisterVariable(&r_test);
4405         Cvar_RegisterVariable(&r_batch_multidraw);
4406         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4407         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4408         Cvar_RegisterVariable(&r_glsl_skeletal);
4409         Cvar_RegisterVariable(&r_glsl_saturation);
4410         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4411         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4412         Cvar_RegisterVariable(&r_framedatasize);
4413         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4414                 Cvar_RegisterVariable(&r_buffermegs[i]);
4415         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4416         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4417                 Cvar_SetValue("r_fullbrights", 0);
4418 #ifdef DP_MOBILETOUCH
4419         // GLES devices have terrible depth precision in general, so...
4420         Cvar_SetValueQuick(&r_nearclip, 4);
4421         Cvar_SetValueQuick(&r_farclip_base, 4096);
4422         Cvar_SetValueQuick(&r_farclip_world, 0);
4423         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4424 #endif
4425         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4426 }
4427
4428 void Render_Init(void)
4429 {
4430         gl_backend_init();
4431         R_Textures_Init();
4432         GL_Main_Init();
4433         Font_Init();
4434         GL_Draw_Init();
4435         R_Shadow_Init();
4436         R_Sky_Init();
4437         GL_Surf_Init();
4438         Sbar_Init();
4439         R_Particles_Init();
4440         R_Explosion_Init();
4441         R_LightningBeams_Init();
4442         Mod_RenderInit();
4443 }
4444
4445 /*
4446 ===============
4447 GL_Init
4448 ===============
4449 */
4450 #ifndef USE_GLES2
4451 extern char *ENGINE_EXTENSIONS;
4452 void GL_Init (void)
4453 {
4454         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4455         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4456         gl_version = (const char *)qglGetString(GL_VERSION);
4457         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4458
4459         if (!gl_extensions)
4460                 gl_extensions = "";
4461         if (!gl_platformextensions)
4462                 gl_platformextensions = "";
4463
4464         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4465         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4466         Con_Printf("GL_VERSION: %s\n", gl_version);
4467         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4468         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4469
4470         VID_CheckExtensions();
4471
4472         // LordHavoc: report supported extensions
4473 #ifdef CONFIG_MENU
4474         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4475 #else
4476         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4477 #endif
4478
4479         // clear to black (loading plaque will be seen over this)
4480         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4481 }
4482 #endif
4483
4484 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4485 {
4486         int i;
4487         mplane_t *p;
4488         if (r_trippy.integer)
4489                 return false;
4490         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4491         {
4492                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4493                 if (i == 4)
4494                         continue;
4495                 p = r_refdef.view.frustum + i;
4496                 switch(p->signbits)
4497                 {
4498                 default:
4499                 case 0:
4500                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4501                                 return true;
4502                         break;
4503                 case 1:
4504                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4505                                 return true;
4506                         break;
4507                 case 2:
4508                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4509                                 return true;
4510                         break;
4511                 case 3:
4512                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4513                                 return true;
4514                         break;
4515                 case 4:
4516                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4517                                 return true;
4518                         break;
4519                 case 5:
4520                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4521                                 return true;
4522                         break;
4523                 case 6:
4524                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4525                                 return true;
4526                         break;
4527                 case 7:
4528                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4529                                 return true;
4530                         break;
4531                 }
4532         }
4533         return false;
4534 }
4535
4536 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4537 {
4538         int i;
4539         const mplane_t *p;
4540         if (r_trippy.integer)
4541                 return false;
4542         for (i = 0;i < numplanes;i++)
4543         {
4544                 p = planes + i;
4545                 switch(p->signbits)
4546                 {
4547                 default:
4548                 case 0:
4549                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4550                                 return true;
4551                         break;
4552                 case 1:
4553                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4554                                 return true;
4555                         break;
4556                 case 2:
4557                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4558                                 return true;
4559                         break;
4560                 case 3:
4561                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4562                                 return true;
4563                         break;
4564                 case 4:
4565                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4566                                 return true;
4567                         break;
4568                 case 5:
4569                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4570                                 return true;
4571                         break;
4572                 case 6:
4573                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4574                                 return true;
4575                         break;
4576                 case 7:
4577                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4578                                 return true;
4579                         break;
4580                 }
4581         }
4582         return false;
4583 }
4584
4585 //==================================================================================
4586
4587 // LordHavoc: this stores temporary data used within the same frame
4588
4589 typedef struct r_framedata_mem_s
4590 {
4591         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4592         size_t size; // how much usable space
4593         size_t current; // how much space in use
4594         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4595         size_t wantedsize; // how much space was allocated
4596         unsigned char *data; // start of real data (16byte aligned)
4597 }
4598 r_framedata_mem_t;
4599
4600 static r_framedata_mem_t *r_framedata_mem;
4601
4602 void R_FrameData_Reset(void)
4603 {
4604         while (r_framedata_mem)
4605         {
4606                 r_framedata_mem_t *next = r_framedata_mem->purge;
4607                 Mem_Free(r_framedata_mem);
4608                 r_framedata_mem = next;
4609         }
4610 }
4611
4612 static void R_FrameData_Resize(qboolean mustgrow)
4613 {
4614         size_t wantedsize;
4615         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4616         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4617         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4618         {
4619                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4620                 newmem->wantedsize = wantedsize;
4621                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4622                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4623                 newmem->current = 0;
4624                 newmem->mark = 0;
4625                 newmem->purge = r_framedata_mem;
4626                 r_framedata_mem = newmem;
4627         }
4628 }
4629
4630 void R_FrameData_NewFrame(void)
4631 {
4632         R_FrameData_Resize(false);
4633         if (!r_framedata_mem)
4634                 return;
4635         // if we ran out of space on the last frame, free the old memory now
4636         while (r_framedata_mem->purge)
4637         {
4638                 // repeatedly remove the second item in the list, leaving only head
4639                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4640                 Mem_Free(r_framedata_mem->purge);
4641                 r_framedata_mem->purge = next;
4642         }
4643         // reset the current mem pointer
4644         r_framedata_mem->current = 0;
4645         r_framedata_mem->mark = 0;
4646 }
4647
4648 void *R_FrameData_Alloc(size_t size)
4649 {
4650         void *data;
4651         float newvalue;
4652
4653         // align to 16 byte boundary - the data pointer is already aligned, so we
4654         // only need to ensure the size of every allocation is also aligned
4655         size = (size + 15) & ~15;
4656
4657         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4658         {
4659                 // emergency - we ran out of space, allocate more memory
4660                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4661                 // this might not be a growing it, but we'll allocate another buffer every time
4662                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4663                 R_FrameData_Resize(true);
4664         }
4665
4666         data = r_framedata_mem->data + r_framedata_mem->current;
4667         r_framedata_mem->current += size;
4668
4669         // count the usage for stats
4670         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4671         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4672
4673         return (void *)data;
4674 }
4675
4676 void *R_FrameData_Store(size_t size, void *data)
4677 {
4678         void *d = R_FrameData_Alloc(size);
4679         if (d && data)
4680                 memcpy(d, data, size);
4681         return d;
4682 }
4683
4684 void R_FrameData_SetMark(void)
4685 {
4686         if (!r_framedata_mem)
4687                 return;
4688         r_framedata_mem->mark = r_framedata_mem->current;
4689 }
4690
4691 void R_FrameData_ReturnToMark(void)
4692 {
4693         if (!r_framedata_mem)
4694                 return;
4695         r_framedata_mem->current = r_framedata_mem->mark;
4696 }
4697
4698 //==================================================================================
4699
4700 // avoid reusing the same buffer objects on consecutive frames
4701 #define R_BUFFERDATA_CYCLE 3
4702
4703 typedef struct r_bufferdata_buffer_s
4704 {
4705         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4706         size_t size; // how much usable space
4707         size_t current; // how much space in use
4708         r_meshbuffer_t *buffer; // the buffer itself
4709 }
4710 r_bufferdata_buffer_t;
4711
4712 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4713 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4714
4715 /// frees all dynamic buffers
4716 void R_BufferData_Reset(void)
4717 {
4718         int cycle, type;
4719         r_bufferdata_buffer_t **p, *mem;
4720         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4721         {
4722                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4723                 {
4724                         // free all buffers
4725                         p = &r_bufferdata_buffer[cycle][type];
4726                         while (*p)
4727                         {
4728                                 mem = *p;
4729                                 *p = (*p)->purge;
4730                                 if (mem->buffer)
4731                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4732                                 Mem_Free(mem);
4733                         }
4734                 }
4735         }
4736 }
4737
4738 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4739 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4740 {
4741         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4742         size_t size;
4743         float newvalue = r_buffermegs[type].value;
4744
4745         // increase the cvar if we have to (but only if we already have a mem)
4746         if (mustgrow && mem)
4747                 newvalue *= 2.0f;
4748         newvalue = bound(0.25f, newvalue, 256.0f);
4749         while (newvalue * 1024*1024 < minsize)
4750                 newvalue *= 2.0f;
4751
4752         // clamp the cvar to valid range
4753         newvalue = bound(0.25f, newvalue, 256.0f);
4754         if (r_buffermegs[type].value != newvalue)
4755                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4756
4757         // calculate size in bytes
4758         size = (size_t)(newvalue * 1024*1024);
4759         size = bound(131072, size, 256*1024*1024);
4760
4761         // allocate a new buffer if the size is different (purge old one later)
4762         // or if we were told we must grow the buffer
4763         if (!mem || mem->size != size || mustgrow)
4764         {
4765                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4766                 mem->size = size;
4767                 mem->current = 0;
4768                 if (type == R_BUFFERDATA_VERTEX)
4769                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4770                 else if (type == R_BUFFERDATA_INDEX16)
4771                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4772                 else if (type == R_BUFFERDATA_INDEX32)
4773                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4774                 else if (type == R_BUFFERDATA_UNIFORM)
4775                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4776                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4777                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4778         }
4779 }
4780
4781 void R_BufferData_NewFrame(void)
4782 {
4783         int type;
4784         r_bufferdata_buffer_t **p, *mem;
4785         // cycle to the next frame's buffers
4786         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4787         // if we ran out of space on the last time we used these buffers, free the old memory now
4788         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4789         {
4790                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4791                 {
4792                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4793                         // free all but the head buffer, this is how we recycle obsolete
4794                         // buffers after they are no longer in use
4795                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4796                         while (*p)
4797                         {
4798                                 mem = *p;
4799                                 *p = (*p)->purge;
4800                                 if (mem->buffer)
4801                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4802                                 Mem_Free(mem);
4803                         }
4804                         // reset the current offset
4805                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4806                 }
4807         }
4808 }
4809
4810 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4811 {
4812         r_bufferdata_buffer_t *mem;
4813         int offset = 0;
4814         int padsize;
4815
4816         *returnbufferoffset = 0;
4817
4818         // align size to a byte boundary appropriate for the buffer type, this
4819         // makes all allocations have aligned start offsets
4820         if (type == R_BUFFERDATA_UNIFORM)
4821                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4822         else
4823                 padsize = (datasize + 15) & ~15;
4824
4825         // if we ran out of space in this buffer we must allocate a new one
4826         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)
4827                 R_BufferData_Resize(type, true, padsize);
4828
4829         // if the resize did not give us enough memory, fail
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                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4832
4833         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4834         offset = mem->current;
4835         mem->current += padsize;
4836
4837         // upload the data to the buffer at the chosen offset
4838         if (offset == 0)
4839                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4840         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4841
4842         // count the usage for stats
4843         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4844         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4845
4846         // return the buffer offset
4847         *returnbufferoffset = offset;
4848
4849         return mem->buffer;
4850 }
4851
4852 //==================================================================================
4853
4854 // LordHavoc: animcache originally written by Echon, rewritten since then
4855
4856 /**
4857  * Animation cache prevents re-generating mesh data for an animated model
4858  * multiple times in one frame for lighting, shadowing, reflections, etc.
4859  */
4860
4861 void R_AnimCache_Free(void)
4862 {
4863 }
4864
4865 void R_AnimCache_ClearCache(void)
4866 {
4867         int i;
4868         entity_render_t *ent;
4869
4870         for (i = 0;i < r_refdef.scene.numentities;i++)
4871         {
4872                 ent = r_refdef.scene.entities[i];
4873                 ent->animcache_vertex3f = NULL;
4874                 ent->animcache_vertex3f_vertexbuffer = NULL;
4875                 ent->animcache_vertex3f_bufferoffset = 0;
4876                 ent->animcache_normal3f = NULL;
4877                 ent->animcache_normal3f_vertexbuffer = NULL;
4878                 ent->animcache_normal3f_bufferoffset = 0;
4879                 ent->animcache_svector3f = NULL;
4880                 ent->animcache_svector3f_vertexbuffer = NULL;
4881                 ent->animcache_svector3f_bufferoffset = 0;
4882                 ent->animcache_tvector3f = NULL;
4883                 ent->animcache_tvector3f_vertexbuffer = NULL;
4884                 ent->animcache_tvector3f_bufferoffset = 0;
4885                 ent->animcache_vertexmesh = NULL;
4886                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4887                 ent->animcache_vertexmesh_bufferoffset = 0;
4888                 ent->animcache_skeletaltransform3x4 = NULL;
4889                 ent->animcache_skeletaltransform3x4buffer = NULL;
4890                 ent->animcache_skeletaltransform3x4offset = 0;
4891                 ent->animcache_skeletaltransform3x4size = 0;
4892         }
4893 }
4894
4895 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4896 {
4897         int i;
4898
4899         // check if we need the meshbuffers
4900         if (!vid.useinterleavedarrays)
4901                 return;
4902
4903         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4904                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4905         // TODO: upload vertexbuffer?
4906         if (ent->animcache_vertexmesh)
4907         {
4908                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4909                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4910                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4911                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4912                 for (i = 0;i < numvertices;i++)
4913                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4914                 if (ent->animcache_svector3f)
4915                         for (i = 0;i < numvertices;i++)
4916                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4917                 if (ent->animcache_tvector3f)
4918                         for (i = 0;i < numvertices;i++)
4919                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4920                 if (ent->animcache_normal3f)
4921                         for (i = 0;i < numvertices;i++)
4922                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4923         }
4924 }
4925
4926 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4927 {
4928         dp_model_t *model = ent->model;
4929         int numvertices;
4930
4931         // see if this ent is worth caching
4932         if (!model || !model->Draw || !model->AnimateVertices)
4933                 return false;
4934         // nothing to cache if it contains no animations and has no skeleton
4935         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4936                 return false;
4937         // see if it is already cached for gpuskeletal
4938         if (ent->animcache_skeletaltransform3x4)
4939                 return false;
4940         // see if it is already cached as a mesh
4941         if (ent->animcache_vertex3f)
4942         {
4943                 // check if we need to add normals or tangents
4944                 if (ent->animcache_normal3f)
4945                         wantnormals = false;
4946                 if (ent->animcache_svector3f)
4947                         wanttangents = false;
4948                 if (!wantnormals && !wanttangents)
4949                         return false;
4950         }
4951
4952         // check which kind of cache we need to generate
4953         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4954         {
4955                 // cache the skeleton so the vertex shader can use it
4956                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4957                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4958                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4959                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4960                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4961                 // note: this can fail if the buffer is at the grow limit
4962                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4963                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4964         }
4965         else if (ent->animcache_vertex3f)
4966         {
4967                 // mesh was already cached but we may need to add normals/tangents
4968                 // (this only happens with multiple views, reflections, cameras, etc)
4969                 if (wantnormals || wanttangents)
4970                 {
4971                         numvertices = model->surfmesh.num_vertices;
4972                         if (wantnormals)
4973                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4974                         if (wanttangents)
4975                         {
4976                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4977                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4978                         }
4979                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4980                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4981                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4982                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4983                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4984                 }
4985         }
4986         else
4987         {
4988                 // generate mesh cache
4989                 numvertices = model->surfmesh.num_vertices;
4990                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4991                 if (wantnormals)
4992                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4993                 if (wanttangents)
4994                 {
4995                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4996                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4997                 }
4998                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4999                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5000                 if (wantnormals || wanttangents)
5001                 {
5002                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5003                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5004                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5005                 }
5006                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5007                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5008                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5009         }
5010         return true;
5011 }
5012
5013 void R_AnimCache_CacheVisibleEntities(void)
5014 {
5015         int i;
5016         qboolean wantnormals = true;
5017         qboolean wanttangents = !r_showsurfaces.integer;
5018
5019         switch(vid.renderpath)
5020         {
5021         case RENDERPATH_GL20:
5022         case RENDERPATH_D3D9:
5023         case RENDERPATH_D3D10:
5024         case RENDERPATH_D3D11:
5025         case RENDERPATH_GLES2:
5026                 break;
5027         case RENDERPATH_GL11:
5028         case RENDERPATH_GL13:
5029         case RENDERPATH_GLES1:
5030                 wanttangents = false;
5031                 break;
5032         case RENDERPATH_SOFT:
5033                 break;
5034         }
5035
5036         if (r_shownormals.integer)
5037                 wanttangents = wantnormals = true;
5038
5039         // TODO: thread this
5040         // NOTE: R_PrepareRTLights() also caches entities
5041
5042         for (i = 0;i < r_refdef.scene.numentities;i++)
5043                 if (r_refdef.viewcache.entityvisible[i])
5044                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5045 }
5046
5047 //==================================================================================
5048
5049 extern cvar_t r_overheadsprites_pushback;
5050
5051 static void R_View_UpdateEntityLighting (void)
5052 {
5053         int i;
5054         entity_render_t *ent;
5055         vec3_t tempdiffusenormal, avg;
5056         vec_t f, fa, fd, fdd;
5057         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5058
5059         for (i = 0;i < r_refdef.scene.numentities;i++)
5060         {
5061                 ent = r_refdef.scene.entities[i];
5062
5063                 // skip unseen models
5064                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5065                         continue;
5066
5067                 // skip bsp models
5068                 if (ent->model && ent->model == cl.worldmodel)
5069                 {
5070                         // TODO: use modellight for r_ambient settings on world?
5071                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5072                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5073                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5074                         continue;
5075                 }
5076                 
5077                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5078                 {
5079                         // aleady updated by CSQC
5080                         // TODO: force modellight on BSP models in this case?
5081                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5082                 }
5083                 else
5084                 {
5085                         // fetch the lighting from the worldmodel data
5086                         VectorClear(ent->modellight_ambient);
5087                         VectorClear(ent->modellight_diffuse);
5088                         VectorClear(tempdiffusenormal);
5089                         if (ent->flags & RENDER_LIGHT)
5090                         {
5091                                 vec3_t org;
5092                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5093
5094                                 // complete lightning for lit sprites
5095                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5096                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5097                                 {
5098                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5099                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5100                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5101                                 }
5102                                 else
5103                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5104
5105                                 if(ent->flags & RENDER_EQUALIZE)
5106                                 {
5107                                         // first fix up ambient lighting...
5108                                         if(r_equalize_entities_minambient.value > 0)
5109                                         {
5110                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5111                                                 if(fd > 0)
5112                                                 {
5113                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5114                                                         if(fa < r_equalize_entities_minambient.value * fd)
5115                                                         {
5116                                                                 // solve:
5117                                                                 //   fa'/fd' = minambient
5118                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5119                                                                 //   ...
5120                                                                 //   fa' = fd' * minambient
5121                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5122                                                                 //   ...
5123                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5124                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5125                                                                 //   ...
5126                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5127                                                                 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
5128                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5129                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5130                                                         }
5131                                                 }
5132                                         }
5133
5134                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5135                                         {
5136                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5137                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5138                                                 f = fa + 0.25 * fd;
5139                                                 if(f > 0)
5140                                                 {
5141                                                         // adjust brightness and saturation to target
5142                                                         avg[0] = avg[1] = avg[2] = fa / f;
5143                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5144                                                         avg[0] = avg[1] = avg[2] = fd / f;
5145                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5146                                                 }
5147                                         }
5148                                 }
5149                         }
5150                         else // highly rare
5151                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5152                 }
5153
5154                 // move the light direction into modelspace coordinates for lighting code
5155                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5156                 if(VectorLength2(ent->modellight_lightdir) == 0)
5157                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5158                 VectorNormalize(ent->modellight_lightdir);
5159         }
5160 }
5161
5162 #define MAX_LINEOFSIGHTTRACES 64
5163
5164 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5165 {
5166         int i;
5167         vec3_t boxmins, boxmaxs;
5168         vec3_t start;
5169         vec3_t end;
5170         dp_model_t *model = r_refdef.scene.worldmodel;
5171
5172         if (!model || !model->brush.TraceLineOfSight)
5173                 return true;
5174
5175         // expand the box a little
5176         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5177         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5178         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5179         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5180         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5181         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5182
5183         // return true if eye is inside enlarged box
5184         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5185                 return true;
5186
5187         // try center
5188         VectorCopy(eye, start);
5189         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5190         if (model->brush.TraceLineOfSight(model, start, end))
5191                 return true;
5192
5193         // try various random positions
5194         for (i = 0;i < numsamples;i++)
5195         {
5196                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5197                 if (model->brush.TraceLineOfSight(model, start, end))
5198                         return true;
5199         }
5200
5201         return false;
5202 }
5203
5204
5205 static void R_View_UpdateEntityVisible (void)
5206 {
5207         int i;
5208         int renderimask;
5209         int samples;
5210         entity_render_t *ent;
5211
5212         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5213                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5214                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5215                 :                                                          RENDER_EXTERIORMODEL;
5216         if (!r_drawviewmodel.integer)
5217                 renderimask |= RENDER_VIEWMODEL;
5218         if (!r_drawexteriormodel.integer)
5219                 renderimask |= RENDER_EXTERIORMODEL;
5220         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5221         {
5222                 // worldmodel can check visibility
5223                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5224                 for (i = 0;i < r_refdef.scene.numentities;i++)
5225                 {
5226                         ent = r_refdef.scene.entities[i];
5227                         if (!(ent->flags & renderimask))
5228                         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)))
5229                         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))
5230                                 r_refdef.viewcache.entityvisible[i] = true;
5231                 }
5232         }
5233         else
5234         {
5235                 // no worldmodel or it can't check visibility
5236                 for (i = 0;i < r_refdef.scene.numentities;i++)
5237                 {
5238                         ent = r_refdef.scene.entities[i];
5239                         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));
5240                 }
5241         }
5242         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5243                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5244         {
5245                 for (i = 0;i < r_refdef.scene.numentities;i++)
5246                 {
5247                         if (!r_refdef.viewcache.entityvisible[i])
5248                                 continue;
5249                         ent = r_refdef.scene.entities[i];
5250                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5251                         {
5252                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5253                                 if (samples < 0)
5254                                         continue; // temp entities do pvs only
5255                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5256                                         ent->last_trace_visibility = realtime;
5257                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5258                                         r_refdef.viewcache.entityvisible[i] = 0;
5259                         }
5260                 }
5261         }
5262 }
5263
5264 /// only used if skyrendermasked, and normally returns false
5265 static int R_DrawBrushModelsSky (void)
5266 {
5267         int i, sky;
5268         entity_render_t *ent;
5269
5270         sky = false;
5271         for (i = 0;i < r_refdef.scene.numentities;i++)
5272         {
5273                 if (!r_refdef.viewcache.entityvisible[i])
5274                         continue;
5275                 ent = r_refdef.scene.entities[i];
5276                 if (!ent->model || !ent->model->DrawSky)
5277                         continue;
5278                 ent->model->DrawSky(ent);
5279                 sky = true;
5280         }
5281         return sky;
5282 }
5283
5284 static void R_DrawNoModel(entity_render_t *ent);
5285 static void R_DrawModels(void)
5286 {
5287         int i;
5288         entity_render_t *ent;
5289
5290         for (i = 0;i < r_refdef.scene.numentities;i++)
5291         {
5292                 if (!r_refdef.viewcache.entityvisible[i])
5293                         continue;
5294                 ent = r_refdef.scene.entities[i];
5295                 r_refdef.stats[r_stat_entities]++;
5296                 /*
5297                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5298                 {
5299                         vec3_t f, l, u, o;
5300                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5301                         Con_Printf("R_DrawModels\n");
5302                         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]);
5303                         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);
5304                         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);
5305                 }
5306                 */
5307                 if (ent->model && ent->model->Draw != NULL)
5308                         ent->model->Draw(ent);
5309                 else
5310                         R_DrawNoModel(ent);
5311         }
5312 }
5313
5314 static void R_DrawModelsDepth(void)
5315 {
5316         int i;
5317         entity_render_t *ent;
5318
5319         for (i = 0;i < r_refdef.scene.numentities;i++)
5320         {
5321                 if (!r_refdef.viewcache.entityvisible[i])
5322                         continue;
5323                 ent = r_refdef.scene.entities[i];
5324                 if (ent->model && ent->model->DrawDepth != NULL)
5325                         ent->model->DrawDepth(ent);
5326         }
5327 }
5328
5329 static void R_DrawModelsDebug(void)
5330 {
5331         int i;
5332         entity_render_t *ent;
5333
5334         for (i = 0;i < r_refdef.scene.numentities;i++)
5335         {
5336                 if (!r_refdef.viewcache.entityvisible[i])
5337                         continue;
5338                 ent = r_refdef.scene.entities[i];
5339                 if (ent->model && ent->model->DrawDebug != NULL)
5340                         ent->model->DrawDebug(ent);
5341         }
5342 }
5343
5344 static void R_DrawModelsAddWaterPlanes(void)
5345 {
5346         int i;
5347         entity_render_t *ent;
5348
5349         for (i = 0;i < r_refdef.scene.numentities;i++)
5350         {
5351                 if (!r_refdef.viewcache.entityvisible[i])
5352                         continue;
5353                 ent = r_refdef.scene.entities[i];
5354                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5355                         ent->model->DrawAddWaterPlanes(ent);
5356         }
5357 }
5358
5359 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}};
5360
5361 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5362 {
5363         if (r_hdr_irisadaptation.integer)
5364         {
5365                 vec3_t p;
5366                 vec3_t ambient;
5367                 vec3_t diffuse;
5368                 vec3_t diffusenormal;
5369                 vec3_t forward;
5370                 vec_t brightness = 0.0f;
5371                 vec_t goal;
5372                 vec_t current;
5373                 vec_t d;
5374                 int c;
5375                 VectorCopy(r_refdef.view.forward, forward);
5376                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5377                 {
5378                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5379                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5380                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5381                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5382                         d = DotProduct(forward, diffusenormal);
5383                         brightness += VectorLength(ambient);
5384                         if (d > 0)
5385                                 brightness += d * VectorLength(diffuse);
5386                 }
5387                 brightness *= 1.0f / c;
5388                 brightness += 0.00001f; // make sure it's never zero
5389                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5390                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5391                 current = r_hdr_irisadaptation_value.value;
5392                 if (current < goal)
5393                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5394                 else if (current > goal)
5395                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5396                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5397                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5398         }
5399         else if (r_hdr_irisadaptation_value.value != 1.0f)
5400                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5401 }
5402
5403 static void R_View_SetFrustum(const int *scissor)
5404 {
5405         int i;
5406         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5407         vec3_t forward, left, up, origin, v;
5408
5409         if(scissor)
5410         {
5411                 // flipped x coordinates (because x points left here)
5412                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5413                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5414
5415                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5416                 switch(vid.renderpath)
5417                 {
5418                         case RENDERPATH_D3D9:
5419                         case RENDERPATH_D3D10:
5420                         case RENDERPATH_D3D11:
5421                                 // non-flipped y coordinates
5422                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5423                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5424                                 break;
5425                         case RENDERPATH_SOFT:
5426                         case RENDERPATH_GL11:
5427                         case RENDERPATH_GL13:
5428                         case RENDERPATH_GL20:
5429                         case RENDERPATH_GLES1:
5430                         case RENDERPATH_GLES2:
5431                                 // non-flipped y coordinates
5432                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5433                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5434                                 break;
5435                 }
5436         }
5437
5438         // we can't trust r_refdef.view.forward and friends in reflected scenes
5439         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5440
5441 #if 0
5442         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5443         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5444         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5445         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5446         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5447         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5448         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5449         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5450         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5451         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5452         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5453         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5454 #endif
5455
5456 #if 0
5457         zNear = r_refdef.nearclip;
5458         nudge = 1.0 - 1.0 / (1<<23);
5459         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5460         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5461         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5462         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5463         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5464         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5465         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5466         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5467 #endif
5468
5469
5470
5471 #if 0
5472         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5473         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5474         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5475         r_refdef.view.frustum[0].dist = m[15] - m[12];
5476
5477         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5478         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5479         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5480         r_refdef.view.frustum[1].dist = m[15] + m[12];
5481
5482         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5483         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5484         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5485         r_refdef.view.frustum[2].dist = m[15] - m[13];
5486
5487         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5488         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5489         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5490         r_refdef.view.frustum[3].dist = m[15] + m[13];
5491
5492         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5493         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5494         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5495         r_refdef.view.frustum[4].dist = m[15] - m[14];
5496
5497         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5498         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5499         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5500         r_refdef.view.frustum[5].dist = m[15] + m[14];
5501 #endif
5502
5503         if (r_refdef.view.useperspective)
5504         {
5505                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5506                 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]);
5507                 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]);
5508                 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]);
5509                 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]);
5510
5511                 // then the normals from the corners relative to origin
5512                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5513                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5514                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5515                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5516
5517                 // in a NORMAL view, forward cross left == up
5518                 // in a REFLECTED view, forward cross left == down
5519                 // so our cross products above need to be adjusted for a left handed coordinate system
5520                 CrossProduct(forward, left, v);
5521                 if(DotProduct(v, up) < 0)
5522                 {
5523                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5524                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5525                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5526                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5527                 }
5528
5529                 // Leaving those out was a mistake, those were in the old code, and they
5530                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5531                 // I couldn't reproduce it after adding those normalizations. --blub
5532                 VectorNormalize(r_refdef.view.frustum[0].normal);
5533                 VectorNormalize(r_refdef.view.frustum[1].normal);
5534                 VectorNormalize(r_refdef.view.frustum[2].normal);
5535                 VectorNormalize(r_refdef.view.frustum[3].normal);
5536
5537                 // make the corners absolute
5538                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5539                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5540                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5541                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5542
5543                 // one more normal
5544                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5545
5546                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5547                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5548                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5549                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5550                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5551         }
5552         else
5553         {
5554                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5555                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5556                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5557                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5558                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5559                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5560                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5561                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5562                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5563                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5564         }
5565         r_refdef.view.numfrustumplanes = 5;
5566
5567         if (r_refdef.view.useclipplane)
5568         {
5569                 r_refdef.view.numfrustumplanes = 6;
5570                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5571         }
5572
5573         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5574                 PlaneClassify(r_refdef.view.frustum + i);
5575
5576         // LordHavoc: note to all quake engine coders, Quake had a special case
5577         // for 90 degrees which assumed a square view (wrong), so I removed it,
5578         // Quake2 has it disabled as well.
5579
5580         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5581         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5582         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5583         //PlaneClassify(&frustum[0]);
5584
5585         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5586         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5587         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5588         //PlaneClassify(&frustum[1]);
5589
5590         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5591         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5592         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5593         //PlaneClassify(&frustum[2]);
5594
5595         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5596         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5597         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5598         //PlaneClassify(&frustum[3]);
5599
5600         // nearclip plane
5601         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5602         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5603         //PlaneClassify(&frustum[4]);
5604 }
5605
5606 static void R_View_UpdateWithScissor(const int *myscissor)
5607 {
5608         R_Main_ResizeViewCache();
5609         R_View_SetFrustum(myscissor);
5610         R_View_WorldVisibility(r_refdef.view.useclipplane);
5611         R_View_UpdateEntityVisible();
5612         R_View_UpdateEntityLighting();
5613 }
5614
5615 static void R_View_Update(void)
5616 {
5617         R_Main_ResizeViewCache();
5618         R_View_SetFrustum(NULL);
5619         R_View_WorldVisibility(r_refdef.view.useclipplane);
5620         R_View_UpdateEntityVisible();
5621         R_View_UpdateEntityLighting();
5622 }
5623
5624 float viewscalefpsadjusted = 1.0f;
5625
5626 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5627 {
5628         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5629         scale = bound(0.03125f, scale, 1.0f);
5630         *outwidth = (int)ceil(width * scale);
5631         *outheight = (int)ceil(height * scale);
5632 }
5633
5634 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5635 {
5636         const float *customclipplane = NULL;
5637         float plane[4];
5638         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5639         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5640         {
5641                 // LordHavoc: couldn't figure out how to make this approach the
5642                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5643                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5644                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5645                         dist = r_refdef.view.clipplane.dist;
5646                 plane[0] = r_refdef.view.clipplane.normal[0];
5647                 plane[1] = r_refdef.view.clipplane.normal[1];
5648                 plane[2] = r_refdef.view.clipplane.normal[2];
5649                 plane[3] = -dist;
5650                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5651         }
5652
5653         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5654         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5655
5656         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5657         if (!r_refdef.view.useperspective)
5658                 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);
5659         else if (vid.stencil && r_useinfinitefarclip.integer)
5660                 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);
5661         else
5662                 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);
5663         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5664         R_SetViewport(&r_refdef.view.viewport);
5665         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5666         {
5667                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5668                 float screenplane[4];
5669                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5670                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5671                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5672                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5673                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5674         }
5675 }
5676
5677 void R_EntityMatrix(const matrix4x4_t *matrix)
5678 {
5679         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5680         {
5681                 gl_modelmatrixchanged = false;
5682                 gl_modelmatrix = *matrix;
5683                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5684                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5685                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5686                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5687                 CHECKGLERROR
5688                 switch(vid.renderpath)
5689                 {
5690                 case RENDERPATH_D3D9:
5691 #ifdef SUPPORTD3D
5692                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5693                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5694 #endif
5695                         break;
5696                 case RENDERPATH_D3D10:
5697                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5698                         break;
5699                 case RENDERPATH_D3D11:
5700                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5701                         break;
5702                 case RENDERPATH_GL11:
5703                 case RENDERPATH_GL13:
5704                 case RENDERPATH_GLES1:
5705 #ifndef USE_GLES2
5706                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5707 #endif
5708                         break;
5709                 case RENDERPATH_SOFT:
5710                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5711                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5712                         break;
5713                 case RENDERPATH_GL20:
5714                 case RENDERPATH_GLES2:
5715                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5716                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5717                         break;
5718                 }
5719         }
5720 }
5721
5722 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5723 {
5724         r_viewport_t viewport;
5725
5726         CHECKGLERROR
5727
5728         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5729         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);
5730         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5731         R_SetViewport(&viewport);
5732         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5733         GL_Color(1, 1, 1, 1);
5734         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5735         GL_BlendFunc(GL_ONE, GL_ZERO);
5736         GL_ScissorTest(false);
5737         GL_DepthMask(false);
5738         GL_DepthRange(0, 1);
5739         GL_DepthTest(false);
5740         GL_DepthFunc(GL_LEQUAL);
5741         R_EntityMatrix(&identitymatrix);
5742         R_Mesh_ResetTextureState();
5743         GL_PolygonOffset(0, 0);
5744         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5745         switch(vid.renderpath)
5746         {
5747         case RENDERPATH_GL11:
5748         case RENDERPATH_GL13:
5749         case RENDERPATH_GL20:
5750         case RENDERPATH_GLES1:
5751         case RENDERPATH_GLES2:
5752                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5753                 break;
5754         case RENDERPATH_D3D9:
5755         case RENDERPATH_D3D10:
5756         case RENDERPATH_D3D11:
5757         case RENDERPATH_SOFT:
5758                 break;
5759         }
5760         GL_CullFace(GL_NONE);
5761
5762         CHECKGLERROR
5763 }
5764
5765 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5766 {
5767         DrawQ_Finish();
5768
5769         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5770 }
5771
5772 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5773 {
5774         DrawQ_Finish();
5775
5776         R_SetupView(true, fbo, depthtexture, colortexture);
5777         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5778         GL_Color(1, 1, 1, 1);
5779         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5780         GL_BlendFunc(GL_ONE, GL_ZERO);
5781         GL_ScissorTest(true);
5782         GL_DepthMask(true);
5783         GL_DepthRange(0, 1);
5784         GL_DepthTest(true);
5785         GL_DepthFunc(GL_LEQUAL);
5786         R_EntityMatrix(&identitymatrix);
5787         R_Mesh_ResetTextureState();
5788         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5789         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5790         switch(vid.renderpath)
5791         {
5792         case RENDERPATH_GL11:
5793         case RENDERPATH_GL13:
5794         case RENDERPATH_GL20:
5795         case RENDERPATH_GLES1:
5796         case RENDERPATH_GLES2:
5797                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5798                 break;
5799         case RENDERPATH_D3D9:
5800         case RENDERPATH_D3D10:
5801         case RENDERPATH_D3D11:
5802         case RENDERPATH_SOFT:
5803                 break;
5804         }
5805         GL_CullFace(r_refdef.view.cullface_back);
5806 }
5807
5808 /*
5809 ================
5810 R_RenderView_UpdateViewVectors
5811 ================
5812 */
5813 void R_RenderView_UpdateViewVectors(void)
5814 {
5815         // break apart the view matrix into vectors for various purposes
5816         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5817         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5818         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5819         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5820         // make an inverted copy of the view matrix for tracking sprites
5821         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5822 }
5823
5824 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5825 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5826
5827 static void R_Water_StartFrame(void)
5828 {
5829         int i;
5830         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5831         r_waterstate_waterplane_t *p;
5832         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;
5833
5834         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5835                 return;
5836
5837         switch(vid.renderpath)
5838         {
5839         case RENDERPATH_GL20:
5840         case RENDERPATH_D3D9:
5841         case RENDERPATH_D3D10:
5842         case RENDERPATH_D3D11:
5843         case RENDERPATH_SOFT:
5844         case RENDERPATH_GLES2:
5845                 break;
5846         case RENDERPATH_GL11:
5847         case RENDERPATH_GL13:
5848         case RENDERPATH_GLES1:
5849                 return;
5850         }
5851
5852         // set waterwidth and waterheight to the water resolution that will be
5853         // used (often less than the screen resolution for faster rendering)
5854         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5855
5856         // calculate desired texture sizes
5857         // can't use water if the card does not support the texture size
5858         if (!r_water.integer || r_showsurfaces.integer)
5859                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5860         else if (vid.support.arb_texture_non_power_of_two)
5861         {
5862                 texturewidth = waterwidth;
5863                 textureheight = waterheight;
5864                 camerawidth = waterwidth;
5865                 cameraheight = waterheight;
5866         }
5867         else
5868         {
5869                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5870                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5871                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5872                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5873         }
5874
5875         // allocate textures as needed
5876         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))
5877         {
5878                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5879                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5880                 {
5881                         if (p->texture_refraction)
5882                                 R_FreeTexture(p->texture_refraction);
5883                         p->texture_refraction = NULL;
5884                         if (p->fbo_refraction)
5885                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5886                         p->fbo_refraction = 0;
5887                         if (p->texture_reflection)
5888                                 R_FreeTexture(p->texture_reflection);
5889                         p->texture_reflection = NULL;
5890                         if (p->fbo_reflection)
5891                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5892                         p->fbo_reflection = 0;
5893                         if (p->texture_camera)
5894                                 R_FreeTexture(p->texture_camera);
5895                         p->texture_camera = NULL;
5896                         if (p->fbo_camera)
5897                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5898                         p->fbo_camera = 0;
5899                 }
5900                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5901                 r_fb.water.texturewidth = texturewidth;
5902                 r_fb.water.textureheight = textureheight;
5903                 r_fb.water.camerawidth = camerawidth;
5904                 r_fb.water.cameraheight = cameraheight;
5905         }
5906
5907         if (r_fb.water.texturewidth)
5908         {
5909                 int scaledwidth, scaledheight;
5910
5911                 r_fb.water.enabled = true;
5912
5913                 // water resolution is usually reduced
5914                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5915                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5916                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5917
5918                 // set up variables that will be used in shader setup
5919                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5920                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5921                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5922                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5923         }
5924
5925         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5926         r_fb.water.numwaterplanes = 0;
5927 }
5928
5929 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5930 {
5931         int planeindex, bestplaneindex, vertexindex;
5932         vec3_t mins, maxs, normal, center, v, n;
5933         vec_t planescore, bestplanescore;
5934         mplane_t plane;
5935         r_waterstate_waterplane_t *p;
5936         texture_t *t = R_GetCurrentTexture(surface->texture);
5937
5938         rsurface.texture = t;
5939         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5940         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5941         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5942                 return;
5943         // average the vertex normals, find the surface bounds (after deformvertexes)
5944         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5945         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5946         VectorCopy(n, normal);
5947         VectorCopy(v, mins);
5948         VectorCopy(v, maxs);
5949         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5950         {
5951                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5952                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5953                 VectorAdd(normal, n, normal);
5954                 mins[0] = min(mins[0], v[0]);
5955                 mins[1] = min(mins[1], v[1]);
5956                 mins[2] = min(mins[2], v[2]);
5957                 maxs[0] = max(maxs[0], v[0]);
5958                 maxs[1] = max(maxs[1], v[1]);
5959                 maxs[2] = max(maxs[2], v[2]);
5960         }
5961         VectorNormalize(normal);
5962         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5963
5964         VectorCopy(normal, plane.normal);
5965         VectorNormalize(plane.normal);
5966         plane.dist = DotProduct(center, plane.normal);
5967         PlaneClassify(&plane);
5968         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5969         {
5970                 // skip backfaces (except if nocullface is set)
5971 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5972 //                      return;
5973                 VectorNegate(plane.normal, plane.normal);
5974                 plane.dist *= -1;
5975                 PlaneClassify(&plane);
5976         }
5977
5978
5979         // find a matching plane if there is one
5980         bestplaneindex = -1;
5981         bestplanescore = 1048576.0f;
5982         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5983         {
5984                 if(p->camera_entity == t->camera_entity)
5985                 {
5986                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5987                         if (bestplaneindex < 0 || bestplanescore > planescore)
5988                         {
5989                                 bestplaneindex = planeindex;
5990                                 bestplanescore = planescore;
5991                         }
5992                 }
5993         }
5994         planeindex = bestplaneindex;
5995         p = r_fb.water.waterplanes + planeindex;
5996
5997         // if this surface does not fit any known plane rendered this frame, add one
5998         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5999         {
6000                 // store the new plane
6001                 planeindex = r_fb.water.numwaterplanes++;
6002                 p = r_fb.water.waterplanes + planeindex;
6003                 p->plane = plane;
6004                 // clear materialflags and pvs
6005                 p->materialflags = 0;
6006                 p->pvsvalid = false;
6007                 p->camera_entity = t->camera_entity;
6008                 VectorCopy(mins, p->mins);
6009                 VectorCopy(maxs, p->maxs);
6010         }
6011         else
6012         {
6013                 // merge mins/maxs when we're adding this surface to the plane
6014                 p->mins[0] = min(p->mins[0], mins[0]);
6015                 p->mins[1] = min(p->mins[1], mins[1]);
6016                 p->mins[2] = min(p->mins[2], mins[2]);
6017                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6018                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6019                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6020         }
6021         // merge this surface's materialflags into the waterplane
6022         p->materialflags |= t->currentmaterialflags;
6023         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6024         {
6025                 // merge this surface's PVS into the waterplane
6026                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6027                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6028                 {
6029                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6030                         p->pvsvalid = true;
6031                 }
6032         }
6033 }
6034
6035 extern cvar_t r_drawparticles;
6036 extern cvar_t r_drawdecals;
6037
6038 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6039 {
6040         int myscissor[4];
6041         r_refdef_view_t originalview;
6042         r_refdef_view_t myview;
6043         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;
6044         r_waterstate_waterplane_t *p;
6045         vec3_t visorigin;
6046         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;
6047         char vabuf[1024];
6048
6049         originalview = r_refdef.view;
6050
6051         // lowquality hack, temporarily shut down some cvars and restore afterwards
6052         qualityreduction = r_water_lowquality.integer;
6053         if (qualityreduction > 0)
6054         {
6055                 if (qualityreduction >= 1)
6056                 {
6057                         old_r_shadows = r_shadows.integer;
6058                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6059                         old_r_dlight = r_shadow_realtime_dlight.integer;
6060                         Cvar_SetValueQuick(&r_shadows, 0);
6061                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6062                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6063                 }
6064                 if (qualityreduction >= 2)
6065                 {
6066                         old_r_dynamic = r_dynamic.integer;
6067                         old_r_particles = r_drawparticles.integer;
6068                         old_r_decals = r_drawdecals.integer;
6069                         Cvar_SetValueQuick(&r_dynamic, 0);
6070                         Cvar_SetValueQuick(&r_drawparticles, 0);
6071                         Cvar_SetValueQuick(&r_drawdecals, 0);
6072                 }
6073         }
6074
6075         // make sure enough textures are allocated
6076         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6077         {
6078                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6079                 {
6080                         if (!p->texture_refraction)
6081                                 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);
6082                         if (!p->texture_refraction)
6083                                 goto error;
6084                         if (usewaterfbo)
6085                         {
6086                                 if (r_fb.water.depthtexture == NULL)
6087                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6088                                 if (p->fbo_refraction == 0)
6089                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6090                         }
6091                 }
6092                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6093                 {
6094                         if (!p->texture_camera)
6095                                 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);
6096                         if (!p->texture_camera)
6097                                 goto error;
6098                         if (usewaterfbo)
6099                         {
6100                                 if (r_fb.water.depthtexture == NULL)
6101                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6102                                 if (p->fbo_camera == 0)
6103                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6104                         }
6105                 }
6106
6107                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6108                 {
6109                         if (!p->texture_reflection)
6110                                 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);
6111                         if (!p->texture_reflection)
6112                                 goto error;
6113                         if (usewaterfbo)
6114                         {
6115                                 if (r_fb.water.depthtexture == NULL)
6116                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6117                                 if (p->fbo_reflection == 0)
6118                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6119                         }
6120                 }
6121         }
6122
6123         // render views
6124         r_refdef.view = originalview;
6125         r_refdef.view.showdebug = false;
6126         r_refdef.view.width = r_fb.water.waterwidth;
6127         r_refdef.view.height = r_fb.water.waterheight;
6128         r_refdef.view.useclipplane = true;
6129         myview = r_refdef.view;
6130         r_fb.water.renderingscene = true;
6131         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6132         {
6133                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6134                 {
6135                         r_refdef.view = myview;
6136                         if(r_water_scissormode.integer)
6137                         {
6138                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6139                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6140                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6141                         }
6142
6143                         // render reflected scene and copy into texture
6144                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6145                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6146                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6147                         r_refdef.view.clipplane = p->plane;
6148                         // reverse the cullface settings for this render
6149                         r_refdef.view.cullface_front = GL_FRONT;
6150                         r_refdef.view.cullface_back = GL_BACK;
6151                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6152                         {
6153                                 r_refdef.view.usecustompvs = true;
6154                                 if (p->pvsvalid)
6155                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6156                                 else
6157                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6158                         }
6159
6160                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6161                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6162                         R_ClearScreen(r_refdef.fogenabled);
6163                         if(r_water_scissormode.integer & 2)
6164                                 R_View_UpdateWithScissor(myscissor);
6165                         else
6166                                 R_View_Update();
6167                         R_AnimCache_CacheVisibleEntities();
6168                         if(r_water_scissormode.integer & 1)
6169                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6170                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6171
6172                         if (!p->fbo_reflection)
6173                                 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);
6174                         r_fb.water.hideplayer = false;
6175                 }
6176
6177                 // render the normal view scene and copy into texture
6178                 // (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)
6179                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6180                 {
6181                         r_refdef.view = myview;
6182                         if(r_water_scissormode.integer)
6183                         {
6184                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6185                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6186                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6187                         }
6188
6189                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6190
6191                         r_refdef.view.clipplane = p->plane;
6192                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6193                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6194
6195                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6196                         {
6197                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6198                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6199                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6200                                 R_RenderView_UpdateViewVectors();
6201                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6202                                 {
6203                                         r_refdef.view.usecustompvs = true;
6204                                         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);
6205                                 }
6206                         }
6207
6208                         PlaneClassify(&r_refdef.view.clipplane);
6209
6210                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6211                         R_ClearScreen(r_refdef.fogenabled);
6212                         if(r_water_scissormode.integer & 2)
6213                                 R_View_UpdateWithScissor(myscissor);
6214                         else
6215                                 R_View_Update();
6216                         R_AnimCache_CacheVisibleEntities();
6217                         if(r_water_scissormode.integer & 1)
6218                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6219                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6220
6221                         if (!p->fbo_refraction)
6222                                 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);
6223                         r_fb.water.hideplayer = false;
6224                 }
6225                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6226                 {
6227                         r_refdef.view = myview;
6228
6229                         r_refdef.view.clipplane = p->plane;
6230                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6231                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6232
6233                         r_refdef.view.width = r_fb.water.camerawidth;
6234                         r_refdef.view.height = r_fb.water.cameraheight;
6235                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6236                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6237                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6238                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6239
6240                         if(p->camera_entity)
6241                         {
6242                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6243                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6244                         }
6245
6246                         // note: all of the view is used for displaying... so
6247                         // there is no use in scissoring
6248
6249                         // reverse the cullface settings for this render
6250                         r_refdef.view.cullface_front = GL_FRONT;
6251                         r_refdef.view.cullface_back = GL_BACK;
6252                         // also reverse the view matrix
6253                         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
6254                         R_RenderView_UpdateViewVectors();
6255                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6256                         {
6257                                 r_refdef.view.usecustompvs = true;
6258                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
6259                         }
6260                         
6261                         // camera needs no clipplane
6262                         r_refdef.view.useclipplane = false;
6263
6264                         PlaneClassify(&r_refdef.view.clipplane);
6265
6266                         r_fb.water.hideplayer = false;
6267
6268                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6269                         R_ClearScreen(r_refdef.fogenabled);
6270                         R_View_Update();
6271                         R_AnimCache_CacheVisibleEntities();
6272                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6273
6274                         if (!p->fbo_camera)
6275                                 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);
6276                         r_fb.water.hideplayer = false;
6277                 }
6278
6279         }
6280         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6281         r_fb.water.renderingscene = false;
6282         r_refdef.view = originalview;
6283         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6284         if (!r_fb.water.depthtexture)
6285                 R_ClearScreen(r_refdef.fogenabled);
6286         R_View_Update();
6287         R_AnimCache_CacheVisibleEntities();
6288         goto finish;
6289 error:
6290         r_refdef.view = originalview;
6291         r_fb.water.renderingscene = false;
6292         Cvar_SetValueQuick(&r_water, 0);
6293         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6294 finish:
6295         // lowquality hack, restore cvars
6296         if (qualityreduction > 0)
6297         {
6298                 if (qualityreduction >= 1)
6299                 {
6300                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6301                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6302                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6303                 }
6304                 if (qualityreduction >= 2)
6305                 {
6306                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6307                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6308                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6309                 }
6310         }
6311 }
6312
6313 static void R_Bloom_StartFrame(void)
6314 {
6315         int i;
6316         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6317         int viewwidth, viewheight;
6318         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6319         textype_t textype = TEXTYPE_COLORBUFFER;
6320
6321         switch (vid.renderpath)
6322         {
6323         case RENDERPATH_GL20:
6324                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6325                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6326                 {
6327                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6328                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6329                 }
6330                 break;
6331         case RENDERPATH_GL11:
6332         case RENDERPATH_GL13:
6333         case RENDERPATH_GLES1:
6334         case RENDERPATH_GLES2:
6335         case RENDERPATH_D3D9:
6336         case RENDERPATH_D3D10:
6337         case RENDERPATH_D3D11:
6338                 r_fb.usedepthtextures = false;
6339                 break;
6340         case RENDERPATH_SOFT:
6341                 r_fb.usedepthtextures = true;
6342                 break;
6343         }
6344
6345         if (r_viewscale_fpsscaling.integer)
6346         {
6347                 double actualframetime;
6348                 double targetframetime;
6349                 double adjust;
6350                 actualframetime = r_refdef.lastdrawscreentime;
6351                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6352                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6353                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6354                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6355                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6356                 viewscalefpsadjusted += adjust;
6357                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6358         }
6359         else
6360                 viewscalefpsadjusted = 1.0f;
6361
6362         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6363
6364         switch(vid.renderpath)
6365         {
6366         case RENDERPATH_GL20:
6367         case RENDERPATH_D3D9:
6368         case RENDERPATH_D3D10:
6369         case RENDERPATH_D3D11:
6370         case RENDERPATH_SOFT:
6371         case RENDERPATH_GLES2:
6372                 break;
6373         case RENDERPATH_GL11:
6374         case RENDERPATH_GL13:
6375         case RENDERPATH_GLES1:
6376                 return;
6377         }
6378
6379         // set bloomwidth and bloomheight to the bloom resolution that will be
6380         // used (often less than the screen resolution for faster rendering)
6381         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6382         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6383         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6384         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6385         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6386
6387         // calculate desired texture sizes
6388         if (vid.support.arb_texture_non_power_of_two)
6389         {
6390                 screentexturewidth = vid.width;
6391                 screentextureheight = vid.height;
6392                 bloomtexturewidth = r_fb.bloomwidth;
6393                 bloomtextureheight = r_fb.bloomheight;
6394         }
6395         else
6396         {
6397                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6398                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6399                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6400                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6401         }
6402
6403         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))
6404         {
6405                 Cvar_SetValueQuick(&r_bloom, 0);
6406                 Cvar_SetValueQuick(&r_motionblur, 0);
6407                 Cvar_SetValueQuick(&r_damageblur, 0);
6408         }
6409
6410         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6411          && !r_bloom.integer
6412          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6413          && !useviewfbo
6414          && r_viewscale.value == 1.0f
6415          && !r_viewscale_fpsscaling.integer)
6416                 screentexturewidth = screentextureheight = 0;
6417         if (!r_bloom.integer)
6418                 bloomtexturewidth = bloomtextureheight = 0;
6419
6420         // allocate textures as needed
6421         if (r_fb.screentexturewidth != screentexturewidth
6422          || r_fb.screentextureheight != screentextureheight
6423          || r_fb.bloomtexturewidth != bloomtexturewidth
6424          || r_fb.bloomtextureheight != bloomtextureheight
6425          || r_fb.textype != textype
6426          || useviewfbo != (r_fb.fbo != 0))
6427         {
6428                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6429                 {
6430                         if (r_fb.bloomtexture[i])
6431                                 R_FreeTexture(r_fb.bloomtexture[i]);
6432                         r_fb.bloomtexture[i] = NULL;
6433
6434                         if (r_fb.bloomfbo[i])
6435                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6436                         r_fb.bloomfbo[i] = 0;
6437                 }
6438
6439                 if (r_fb.fbo)
6440                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6441                 r_fb.fbo = 0;
6442
6443                 if (r_fb.colortexture)
6444                         R_FreeTexture(r_fb.colortexture);
6445                 r_fb.colortexture = NULL;
6446
6447                 if (r_fb.depthtexture)
6448                         R_FreeTexture(r_fb.depthtexture);
6449                 r_fb.depthtexture = NULL;
6450
6451                 if (r_fb.ghosttexture)
6452                         R_FreeTexture(r_fb.ghosttexture);
6453                 r_fb.ghosttexture = NULL;
6454
6455                 r_fb.screentexturewidth = screentexturewidth;
6456                 r_fb.screentextureheight = screentextureheight;
6457                 r_fb.bloomtexturewidth = bloomtexturewidth;
6458                 r_fb.bloomtextureheight = bloomtextureheight;
6459                 r_fb.textype = textype;
6460
6461                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6462                 {
6463                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6464                                 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);
6465                         r_fb.ghosttexture_valid = false;
6466                         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);
6467                         if (useviewfbo)
6468                         {
6469                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6470                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6471                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6472                         }
6473                 }
6474
6475                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6476                 {
6477                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6478                         {
6479                                 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);
6480                                 if (useviewfbo)
6481                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6482                         }
6483                 }
6484         }
6485
6486         // bloom texture is a different resolution
6487         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6488         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6489         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6490         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6491         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6492
6493         // set up a texcoord array for the full resolution screen image
6494         // (we have to keep this around to copy back during final render)
6495         r_fb.screentexcoord2f[0] = 0;
6496         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6497         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6498         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6499         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6500         r_fb.screentexcoord2f[5] = 0;
6501         r_fb.screentexcoord2f[6] = 0;
6502         r_fb.screentexcoord2f[7] = 0;
6503
6504         if(r_fb.fbo) 
6505         {
6506                 for (i = 1;i < 8;i += 2)
6507                 {
6508                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6509                 }
6510         }
6511
6512         // set up a texcoord array for the reduced resolution bloom image
6513         // (which will be additive blended over the screen image)
6514         r_fb.bloomtexcoord2f[0] = 0;
6515         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6516         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6517         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6518         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6519         r_fb.bloomtexcoord2f[5] = 0;
6520         r_fb.bloomtexcoord2f[6] = 0;
6521         r_fb.bloomtexcoord2f[7] = 0;
6522
6523         switch(vid.renderpath)
6524         {
6525         case RENDERPATH_GL11:
6526         case RENDERPATH_GL13:
6527         case RENDERPATH_GL20:
6528         case RENDERPATH_SOFT:
6529         case RENDERPATH_GLES1:
6530         case RENDERPATH_GLES2:
6531                 break;
6532         case RENDERPATH_D3D9:
6533         case RENDERPATH_D3D10:
6534         case RENDERPATH_D3D11:
6535                 for (i = 0;i < 4;i++)
6536                 {
6537                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6538                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6539                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6540                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6541                 }
6542                 break;
6543         }
6544
6545         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6546
6547         if (r_fb.fbo)
6548                 r_refdef.view.clear = true;
6549 }
6550
6551 static void R_Bloom_MakeTexture(void)
6552 {
6553         int x, range, dir;
6554         float xoffset, yoffset, r, brighten;
6555         rtexture_t *intex;
6556         float colorscale = r_bloom_colorscale.value;
6557
6558         r_refdef.stats[r_stat_bloom]++;
6559     
6560 #if 0
6561     // this copy is unnecessary since it happens in R_BlendView already
6562         if (!r_fb.fbo)
6563         {
6564                 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);
6565                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6566         }
6567 #endif
6568
6569         // scale down screen texture to the bloom texture size
6570         CHECKGLERROR
6571         r_fb.bloomindex = 0;
6572         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6573         R_SetViewport(&r_fb.bloomviewport);
6574         GL_DepthTest(false);
6575         GL_BlendFunc(GL_ONE, GL_ZERO);
6576         GL_Color(colorscale, colorscale, colorscale, 1);
6577         // 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...
6578         switch(vid.renderpath)
6579         {
6580         case RENDERPATH_GL11:
6581         case RENDERPATH_GL13:
6582         case RENDERPATH_GL20:
6583         case RENDERPATH_GLES1:
6584         case RENDERPATH_GLES2:
6585         case RENDERPATH_SOFT:
6586                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6587                 break;
6588         case RENDERPATH_D3D9:
6589         case RENDERPATH_D3D10:
6590         case RENDERPATH_D3D11:
6591                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6592                 break;
6593         }
6594         // TODO: do boxfilter scale-down in shader?
6595         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6596         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6597         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6598
6599         // we now have a properly scaled bloom image
6600         if (!r_fb.bloomfbo[r_fb.bloomindex])
6601         {
6602                 // copy it into the bloom texture
6603                 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);
6604                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6605         }
6606
6607         // multiply bloom image by itself as many times as desired
6608         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6609         {
6610                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6611                 r_fb.bloomindex ^= 1;
6612                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6613                 x *= 2;
6614                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6615                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6616                 {
6617                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6618                         GL_Color(r,r,r,1); // apply fix factor
6619                 }
6620                 else
6621                 {
6622                         if(x <= 2)
6623                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6624                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6625                         GL_Color(1,1,1,1); // no fix factor supported here
6626                 }
6627                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6628                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6629                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6630                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6631
6632                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6633                 {
6634                         // copy the darkened image to a texture
6635                         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);
6636                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6637                 }
6638         }
6639
6640         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6641         brighten = r_bloom_brighten.value;
6642         brighten = sqrt(brighten);
6643         if(range >= 1)
6644                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6645
6646         for (dir = 0;dir < 2;dir++)
6647         {
6648                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6649                 r_fb.bloomindex ^= 1;
6650                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6651                 // blend on at multiple vertical offsets to achieve a vertical blur
6652                 // TODO: do offset blends using GLSL
6653                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6654                 GL_BlendFunc(GL_ONE, GL_ZERO);
6655                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6656                 for (x = -range;x <= range;x++)
6657                 {
6658                         if (!dir){xoffset = 0;yoffset = x;}
6659                         else {xoffset = x;yoffset = 0;}
6660                         xoffset /= (float)r_fb.bloomtexturewidth;
6661                         yoffset /= (float)r_fb.bloomtextureheight;
6662                         // compute a texcoord array with the specified x and y offset
6663                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6664                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6665                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6666                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6667                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6668                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6669                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6670                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6671                         // this r value looks like a 'dot' particle, fading sharply to
6672                         // black at the edges
6673                         // (probably not realistic but looks good enough)
6674                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6675                         //r = brighten/(range*2+1);
6676                         r = brighten / (range * 2 + 1);
6677                         if(range >= 1)
6678                                 r *= (1 - x*x/(float)(range*range));
6679                         GL_Color(r, r, r, 1);
6680                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6681                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6682                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6683                         GL_BlendFunc(GL_ONE, GL_ONE);
6684                 }
6685
6686                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6687                 {
6688                         // copy the vertically or horizontally blurred bloom view to a texture
6689                         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);
6690                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6691                 }
6692         }
6693 }
6694
6695 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6696 {
6697         unsigned int permutation;
6698         float uservecs[4][4];
6699
6700         R_EntityMatrix(&identitymatrix);
6701
6702         switch (vid.renderpath)
6703         {
6704         case RENDERPATH_GL20:
6705         case RENDERPATH_D3D9:
6706         case RENDERPATH_D3D10:
6707         case RENDERPATH_D3D11:
6708         case RENDERPATH_SOFT:
6709         case RENDERPATH_GLES2:
6710                 permutation =
6711                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6712                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6713                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6714                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6715                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6716
6717                 if (r_fb.colortexture)
6718                 {
6719                         if (!r_fb.fbo)
6720                         {
6721                                 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);
6722                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6723                         }
6724
6725                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6726                         {
6727                                 // declare variables
6728                                 float blur_factor, blur_mouseaccel, blur_velocity;
6729                                 static float blur_average; 
6730                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6731
6732                                 // set a goal for the factoring
6733                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6734                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6735                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6736                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6737                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6738                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6739
6740                                 // from the goal, pick an averaged value between goal and last value
6741                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6742                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6743
6744                                 // enforce minimum amount of blur 
6745                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6746
6747                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6748
6749                                 // calculate values into a standard alpha
6750                                 cl.motionbluralpha = 1 - exp(-
6751                                                 (
6752                                                  (r_motionblur.value * blur_factor / 80)
6753                                                  +
6754                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6755                                                 )
6756                                                 /
6757                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6758                                           );
6759
6760                                 // randomization for the blur value to combat persistent ghosting
6761                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6762                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6763
6764                                 // apply the blur
6765                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6766                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6767                                 {
6768                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6769                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6770                                         switch(vid.renderpath)
6771                                         {
6772                                         case RENDERPATH_GL11:
6773                                         case RENDERPATH_GL13:
6774                                         case RENDERPATH_GL20:
6775                                         case RENDERPATH_GLES1:
6776                                         case RENDERPATH_GLES2:
6777                                         case RENDERPATH_SOFT:
6778                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6779                                                 break;
6780                                         case RENDERPATH_D3D9:
6781                                         case RENDERPATH_D3D10:
6782                                         case RENDERPATH_D3D11:
6783                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6784                                                 break;
6785                                         }
6786                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6787                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6788                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6789                                 }
6790
6791                                 // updates old view angles for next pass
6792                                 VectorCopy(cl.viewangles, blur_oldangles);
6793
6794                                 // copy view into the ghost texture
6795                                 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);
6796                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6797                                 r_fb.ghosttexture_valid = true;
6798                         }
6799                 }
6800                 else
6801                 {
6802                         // no r_fb.colortexture means we're rendering to the real fb
6803                         // we may still have to do view tint...
6804                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6805                         {
6806                                 // apply a color tint to the whole view
6807                                 R_ResetViewRendering2D(0, NULL, NULL);
6808                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6809                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6810                                 R_SetupShader_Generic_NoTexture(false, true);
6811                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6812                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6813                         }
6814                         break; // no screen processing, no bloom, skip it
6815                 }
6816
6817                 if (r_fb.bloomtexture[0])
6818                 {
6819                         // make the bloom texture
6820                         R_Bloom_MakeTexture();
6821                 }
6822
6823 #if _MSC_VER >= 1400
6824 #define sscanf sscanf_s
6825 #endif
6826                 memset(uservecs, 0, sizeof(uservecs));
6827                 if (r_glsl_postprocess_uservec1_enable.integer)
6828                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6829                 if (r_glsl_postprocess_uservec2_enable.integer)
6830                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6831                 if (r_glsl_postprocess_uservec3_enable.integer)
6832                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6833                 if (r_glsl_postprocess_uservec4_enable.integer)
6834                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6835
6836                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6837                 GL_Color(1, 1, 1, 1);
6838                 GL_BlendFunc(GL_ONE, GL_ZERO);
6839
6840                 switch(vid.renderpath)
6841                 {
6842                 case RENDERPATH_GL20:
6843                 case RENDERPATH_GLES2:
6844                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6845                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6846                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6847                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6848                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6849                         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]);
6850                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6851                         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]);
6852                         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]);
6853                         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]);
6854                         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]);
6855                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6856                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6857                         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);
6858                         break;
6859                 case RENDERPATH_D3D9:
6860 #ifdef SUPPORTD3D
6861                         // 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...
6862                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6863                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6864                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6865                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6866                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6867                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6868                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6869                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6870                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6871                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6872                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6873                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6874                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6875                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6876 #endif
6877                         break;
6878                 case RENDERPATH_D3D10:
6879                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6880                         break;
6881                 case RENDERPATH_D3D11:
6882                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6883                         break;
6884                 case RENDERPATH_SOFT:
6885                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6886                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6887                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6888                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6889                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6890                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6891                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6892                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6893                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6894                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6895                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6896                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6897                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6898                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6899                         break;
6900                 default:
6901                         break;
6902                 }
6903                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6904                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6905                 break;
6906         case RENDERPATH_GL11:
6907         case RENDERPATH_GL13:
6908         case RENDERPATH_GLES1:
6909                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6910                 {
6911                         // apply a color tint to the whole view
6912                         R_ResetViewRendering2D(0, NULL, NULL);
6913                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6914                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6915                         R_SetupShader_Generic_NoTexture(false, true);
6916                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6917                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6918                 }
6919                 break;
6920         }
6921 }
6922
6923 matrix4x4_t r_waterscrollmatrix;
6924
6925 void R_UpdateFog(void)
6926 {
6927         // Nehahra fog
6928         if (gamemode == GAME_NEHAHRA)
6929         {
6930                 if (gl_fogenable.integer)
6931                 {
6932                         r_refdef.oldgl_fogenable = true;
6933                         r_refdef.fog_density = gl_fogdensity.value;
6934                         r_refdef.fog_red = gl_fogred.value;
6935                         r_refdef.fog_green = gl_foggreen.value;
6936                         r_refdef.fog_blue = gl_fogblue.value;
6937                         r_refdef.fog_alpha = 1;
6938                         r_refdef.fog_start = 0;
6939                         r_refdef.fog_end = gl_skyclip.value;
6940                         r_refdef.fog_height = 1<<30;
6941                         r_refdef.fog_fadedepth = 128;
6942                 }
6943                 else if (r_refdef.oldgl_fogenable)
6944                 {
6945                         r_refdef.oldgl_fogenable = false;
6946                         r_refdef.fog_density = 0;
6947                         r_refdef.fog_red = 0;
6948                         r_refdef.fog_green = 0;
6949                         r_refdef.fog_blue = 0;
6950                         r_refdef.fog_alpha = 0;
6951                         r_refdef.fog_start = 0;
6952                         r_refdef.fog_end = 0;
6953                         r_refdef.fog_height = 1<<30;
6954                         r_refdef.fog_fadedepth = 128;
6955                 }
6956         }
6957
6958         // fog parms
6959         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6960         r_refdef.fog_start = max(0, r_refdef.fog_start);
6961         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6962
6963         if (r_refdef.fog_density && r_drawfog.integer)
6964         {
6965                 r_refdef.fogenabled = true;
6966                 // this is the point where the fog reaches 0.9986 alpha, which we
6967                 // consider a good enough cutoff point for the texture
6968                 // (0.9986 * 256 == 255.6)
6969                 if (r_fog_exp2.integer)
6970                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6971                 else
6972                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6973                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6974                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6975                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6976                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6977                         R_BuildFogHeightTexture();
6978                 // fog color was already set
6979                 // update the fog texture
6980                 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)
6981                         R_BuildFogTexture();
6982                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6983                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6984         }
6985         else
6986                 r_refdef.fogenabled = false;
6987
6988         // fog color
6989         if (r_refdef.fog_density)
6990         {
6991                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6992                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6993                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6994
6995                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6996                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6997                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6998                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6999
7000                 {
7001                         vec3_t fogvec;
7002                         VectorCopy(r_refdef.fogcolor, fogvec);
7003                         //   color.rgb *= ContrastBoost * SceneBrightness;
7004                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7005                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7006                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7007                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7008                 }
7009         }
7010 }
7011
7012 void R_UpdateVariables(void)
7013 {
7014         R_Textures_Frame();
7015
7016         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7017
7018         r_refdef.farclip = r_farclip_base.value;
7019         if (r_refdef.scene.worldmodel)
7020                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7021         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7022
7023         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7024                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7025         r_refdef.polygonfactor = 0;
7026         r_refdef.polygonoffset = 0;
7027         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7028         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7029
7030         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7031         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7032         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7033         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7034         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7035         if (FAKELIGHT_ENABLED)
7036         {
7037                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7038         }
7039         else if (r_refdef.scene.worldmodel)
7040         {
7041                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7042         }
7043         if (r_showsurfaces.integer)
7044         {
7045                 r_refdef.scene.rtworld = false;
7046                 r_refdef.scene.rtworldshadows = false;
7047                 r_refdef.scene.rtdlight = false;
7048                 r_refdef.scene.rtdlightshadows = false;
7049                 r_refdef.lightmapintensity = 0;
7050         }
7051
7052         r_gpuskeletal = false;
7053         switch(vid.renderpath)
7054         {
7055         case RENDERPATH_GL20:
7056                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7057         case RENDERPATH_D3D9:
7058         case RENDERPATH_D3D10:
7059         case RENDERPATH_D3D11:
7060         case RENDERPATH_SOFT:
7061         case RENDERPATH_GLES2:
7062                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7063                 {
7064                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7065                         {
7066                                 // build GLSL gamma texture
7067 #define RAMPWIDTH 256
7068                                 unsigned short ramp[RAMPWIDTH * 3];
7069                                 unsigned char rampbgr[RAMPWIDTH][4];
7070                                 int i;
7071
7072                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7073
7074                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7075                                 for(i = 0; i < RAMPWIDTH; ++i)
7076                                 {
7077                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7078                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7079                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7080                                         rampbgr[i][3] = 0;
7081                                 }
7082                                 if (r_texture_gammaramps)
7083                                 {
7084                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7085                                 }
7086                                 else
7087                                 {
7088                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7089                                 }
7090                         }
7091                 }
7092                 else
7093                 {
7094                         // remove GLSL gamma texture
7095                 }
7096                 break;
7097         case RENDERPATH_GL11:
7098         case RENDERPATH_GL13:
7099         case RENDERPATH_GLES1:
7100                 break;
7101         }
7102 }
7103
7104 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7105 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7106 /*
7107 ================
7108 R_SelectScene
7109 ================
7110 */
7111 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7112         if( scenetype != r_currentscenetype ) {
7113                 // store the old scenetype
7114                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7115                 r_currentscenetype = scenetype;
7116                 // move in the new scene
7117                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7118         }
7119 }
7120
7121 /*
7122 ================
7123 R_GetScenePointer
7124 ================
7125 */
7126 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7127 {
7128         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7129         if( scenetype == r_currentscenetype ) {
7130                 return &r_refdef.scene;
7131         } else {
7132                 return &r_scenes_store[ scenetype ];
7133         }
7134 }
7135
7136 static int R_SortEntities_Compare(const void *ap, const void *bp)
7137 {
7138         const entity_render_t *a = *(const entity_render_t **)ap;
7139         const entity_render_t *b = *(const entity_render_t **)bp;
7140
7141         // 1. compare model
7142         if(a->model < b->model)
7143                 return -1;
7144         if(a->model > b->model)
7145                 return +1;
7146
7147         // 2. compare skin
7148         // TODO possibly calculate the REAL skinnum here first using
7149         // skinscenes?
7150         if(a->skinnum < b->skinnum)
7151                 return -1;
7152         if(a->skinnum > b->skinnum)
7153                 return +1;
7154
7155         // everything we compared is equal
7156         return 0;
7157 }
7158 static void R_SortEntities(void)
7159 {
7160         // below or equal 2 ents, sorting never gains anything
7161         if(r_refdef.scene.numentities <= 2)
7162                 return;
7163         // sort
7164         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7165 }
7166
7167 /*
7168 ================
7169 R_RenderView
7170 ================
7171 */
7172 int dpsoftrast_test;
7173 extern cvar_t r_shadow_bouncegrid;
7174 void R_RenderView(void)
7175 {
7176         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7177         int fbo;
7178         rtexture_t *depthtexture;
7179         rtexture_t *colortexture;
7180
7181         dpsoftrast_test = r_test.integer;
7182
7183         if (r_timereport_active)
7184                 R_TimeReport("start");
7185         r_textureframe++; // used only by R_GetCurrentTexture
7186         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7187
7188         if(R_CompileShader_CheckStaticParms())
7189                 R_GLSL_Restart_f();
7190
7191         if (!r_drawentities.integer)
7192                 r_refdef.scene.numentities = 0;
7193         else if (r_sortentities.integer)
7194                 R_SortEntities();
7195
7196         R_AnimCache_ClearCache();
7197
7198         /* adjust for stereo display */
7199         if(R_Stereo_Active())
7200         {
7201                 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);
7202                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7203         }
7204
7205         if (r_refdef.view.isoverlay)
7206         {
7207                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7208                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7209                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7210                 R_TimeReport("depthclear");
7211
7212                 r_refdef.view.showdebug = false;
7213
7214                 r_fb.water.enabled = false;
7215                 r_fb.water.numwaterplanes = 0;
7216
7217                 R_RenderScene(0, NULL, NULL);
7218
7219                 r_refdef.view.matrix = originalmatrix;
7220
7221                 CHECKGLERROR
7222                 return;
7223         }
7224
7225         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7226         {
7227                 r_refdef.view.matrix = originalmatrix;
7228                 return;
7229         }
7230
7231         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7232
7233         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7234                 // in sRGB fallback, behave similar to true sRGB: convert this
7235                 // value from linear to sRGB
7236                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7237
7238         R_RenderView_UpdateViewVectors();
7239
7240         R_Shadow_UpdateWorldLightSelection();
7241
7242         R_Bloom_StartFrame();
7243
7244         // apply bloom brightness offset
7245         if(r_fb.bloomtexture[0])
7246                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7247
7248         R_Water_StartFrame();
7249
7250         // now we probably have an fbo to render into
7251         fbo = r_fb.fbo;
7252         depthtexture = r_fb.depthtexture;
7253         colortexture = r_fb.colortexture;
7254
7255         CHECKGLERROR
7256         if (r_timereport_active)
7257                 R_TimeReport("viewsetup");
7258
7259         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7260
7261         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7262         {
7263                 R_ClearScreen(r_refdef.fogenabled);
7264                 if (r_timereport_active)
7265                         R_TimeReport("viewclear");
7266         }
7267         r_refdef.view.clear = true;
7268
7269         r_refdef.view.showdebug = true;
7270
7271         R_View_Update();
7272         if (r_timereport_active)
7273                 R_TimeReport("visibility");
7274
7275         R_AnimCache_CacheVisibleEntities();
7276         if (r_timereport_active)
7277                 R_TimeReport("animcache");
7278
7279         R_Shadow_UpdateBounceGridTexture();
7280         if (r_timereport_active && r_shadow_bouncegrid.integer)
7281                 R_TimeReport("bouncegrid");
7282
7283         r_fb.water.numwaterplanes = 0;
7284         if (r_fb.water.enabled)
7285                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7286
7287         R_RenderScene(fbo, depthtexture, colortexture);
7288         r_fb.water.numwaterplanes = 0;
7289
7290         R_BlendView(fbo, depthtexture, colortexture);
7291         if (r_timereport_active)
7292                 R_TimeReport("blendview");
7293
7294         GL_Scissor(0, 0, vid.width, vid.height);
7295         GL_ScissorTest(false);
7296
7297         r_refdef.view.matrix = originalmatrix;
7298
7299         CHECKGLERROR
7300 }
7301
7302 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7303 {
7304         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7305         {
7306                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7307                 if (r_timereport_active)
7308                         R_TimeReport("waterworld");
7309         }
7310
7311         // don't let sound skip if going slow
7312         if (r_refdef.scene.extraupdate)
7313                 S_ExtraUpdate ();
7314
7315         R_DrawModelsAddWaterPlanes();
7316         if (r_timereport_active)
7317                 R_TimeReport("watermodels");
7318
7319         if (r_fb.water.numwaterplanes)
7320         {
7321                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7322                 if (r_timereport_active)
7323                         R_TimeReport("waterscenes");
7324         }
7325 }
7326
7327 extern cvar_t cl_locs_show;
7328 static void R_DrawLocs(void);
7329 static void R_DrawEntityBBoxes(void);
7330 static void R_DrawModelDecals(void);
7331 extern cvar_t cl_decals_newsystem;
7332 extern qboolean r_shadow_usingdeferredprepass;
7333 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7334 {
7335         qboolean shadowmapping = false;
7336
7337         if (r_timereport_active)
7338                 R_TimeReport("beginscene");
7339
7340         r_refdef.stats[r_stat_renders]++;
7341
7342         R_UpdateFog();
7343
7344         // don't let sound skip if going slow
7345         if (r_refdef.scene.extraupdate)
7346                 S_ExtraUpdate ();
7347
7348         R_MeshQueue_BeginScene();
7349
7350         R_SkyStartFrame();
7351
7352         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);
7353
7354         if (r_timereport_active)
7355                 R_TimeReport("skystartframe");
7356
7357         if (cl.csqc_vidvars.drawworld)
7358         {
7359                 // don't let sound skip if going slow
7360                 if (r_refdef.scene.extraupdate)
7361                         S_ExtraUpdate ();
7362
7363                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7364                 {
7365                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7366                         if (r_timereport_active)
7367                                 R_TimeReport("worldsky");
7368                 }
7369
7370                 if (R_DrawBrushModelsSky() && r_timereport_active)
7371                         R_TimeReport("bmodelsky");
7372
7373                 if (skyrendermasked && skyrenderlater)
7374                 {
7375                         // we have to force off the water clipping plane while rendering sky
7376                         R_SetupView(false, fbo, depthtexture, colortexture);
7377                         R_Sky();
7378                         R_SetupView(true, fbo, depthtexture, colortexture);
7379                         if (r_timereport_active)
7380                                 R_TimeReport("sky");
7381                 }
7382         }
7383
7384         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7385         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7386                 R_Shadow_PrepareModelShadows();
7387         if (r_timereport_active)
7388                 R_TimeReport("preparelights");
7389
7390         if (R_Shadow_ShadowMappingEnabled())
7391                 shadowmapping = true;
7392
7393         if (r_shadow_usingdeferredprepass)
7394                 R_Shadow_DrawPrepass();
7395
7396         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7397         {
7398                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7399                 if (r_timereport_active)
7400                         R_TimeReport("worlddepth");
7401         }
7402         if (r_depthfirst.integer >= 2)
7403         {
7404                 R_DrawModelsDepth();
7405                 if (r_timereport_active)
7406                         R_TimeReport("modeldepth");
7407         }
7408
7409         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7410         {
7411                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7412                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7413                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7414                 // don't let sound skip if going slow
7415                 if (r_refdef.scene.extraupdate)
7416                         S_ExtraUpdate ();
7417         }
7418
7419         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7420         {
7421                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7422                 if (r_timereport_active)
7423                         R_TimeReport("world");
7424         }
7425
7426         // don't let sound skip if going slow
7427         if (r_refdef.scene.extraupdate)
7428                 S_ExtraUpdate ();
7429
7430         R_DrawModels();
7431         if (r_timereport_active)
7432                 R_TimeReport("models");
7433
7434         // don't let sound skip if going slow
7435         if (r_refdef.scene.extraupdate)
7436                 S_ExtraUpdate ();
7437
7438         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7439         {
7440                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7441                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7442                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7443                 // don't let sound skip if going slow
7444                 if (r_refdef.scene.extraupdate)
7445                         S_ExtraUpdate ();
7446         }
7447
7448         if (!r_shadow_usingdeferredprepass)
7449         {
7450                 R_Shadow_DrawLights();
7451                 if (r_timereport_active)
7452                         R_TimeReport("rtlights");
7453         }
7454
7455         // don't let sound skip if going slow
7456         if (r_refdef.scene.extraupdate)
7457                 S_ExtraUpdate ();
7458
7459         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7460         {
7461                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7462                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7463                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7464                 // don't let sound skip if going slow
7465                 if (r_refdef.scene.extraupdate)
7466                         S_ExtraUpdate ();
7467         }
7468
7469         if (cl.csqc_vidvars.drawworld)
7470         {
7471                 if (cl_decals_newsystem.integer)
7472                 {
7473                         R_DrawModelDecals();
7474                         if (r_timereport_active)
7475                                 R_TimeReport("modeldecals");
7476                 }
7477                 else
7478                 {
7479                         R_DrawDecals();
7480                         if (r_timereport_active)
7481                                 R_TimeReport("decals");
7482                 }
7483
7484                 R_DrawParticles();
7485                 if (r_timereport_active)
7486                         R_TimeReport("particles");
7487
7488                 R_DrawExplosions();
7489                 if (r_timereport_active)
7490                         R_TimeReport("explosions");
7491
7492                 R_DrawLightningBeams();
7493                 if (r_timereport_active)
7494                         R_TimeReport("lightning");
7495         }
7496
7497         if (cl.csqc_loaded)
7498                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7499
7500         if (r_refdef.view.showdebug)
7501         {
7502                 if (cl_locs_show.integer)
7503                 {
7504                         R_DrawLocs();
7505                         if (r_timereport_active)
7506                                 R_TimeReport("showlocs");
7507                 }
7508
7509                 if (r_drawportals.integer)
7510                 {
7511                         R_DrawPortals();
7512                         if (r_timereport_active)
7513                                 R_TimeReport("portals");
7514                 }
7515
7516                 if (r_showbboxes.value > 0)
7517                 {
7518                         R_DrawEntityBBoxes();
7519                         if (r_timereport_active)
7520                                 R_TimeReport("bboxes");
7521                 }
7522         }
7523
7524         if (r_transparent.integer)
7525         {
7526                 R_MeshQueue_RenderTransparent();
7527                 if (r_timereport_active)
7528                         R_TimeReport("drawtrans");
7529         }
7530
7531         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))
7532         {
7533                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7534                 if (r_timereport_active)
7535                         R_TimeReport("worlddebug");
7536                 R_DrawModelsDebug();
7537                 if (r_timereport_active)
7538                         R_TimeReport("modeldebug");
7539         }
7540
7541         if (cl.csqc_vidvars.drawworld)
7542         {
7543                 R_Shadow_DrawCoronas();
7544                 if (r_timereport_active)
7545                         R_TimeReport("coronas");
7546         }
7547
7548 #if 0
7549         {
7550                 GL_DepthTest(false);
7551                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7552                 GL_Color(1, 1, 1, 1);
7553                 qglBegin(GL_POLYGON);
7554                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7555                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7556                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7557                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7558                 qglEnd();
7559                 qglBegin(GL_POLYGON);
7560                 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]);
7561                 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]);
7562                 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]);
7563                 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]);
7564                 qglEnd();
7565                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7566         }
7567 #endif
7568
7569         // don't let sound skip if going slow
7570         if (r_refdef.scene.extraupdate)
7571                 S_ExtraUpdate ();
7572 }
7573
7574 static const unsigned short bboxelements[36] =
7575 {
7576         5, 1, 3, 5, 3, 7,
7577         6, 2, 0, 6, 0, 4,
7578         7, 3, 2, 7, 2, 6,
7579         4, 0, 1, 4, 1, 5,
7580         4, 5, 7, 4, 7, 6,
7581         1, 0, 2, 1, 2, 3,
7582 };
7583
7584 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7585 {
7586         int i;
7587         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7588
7589         RSurf_ActiveWorldEntity();
7590
7591         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7592         GL_DepthMask(false);
7593         GL_DepthRange(0, 1);
7594         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7595 //      R_Mesh_ResetTextureState();
7596
7597         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7598         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7599         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7600         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7601         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7602         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7603         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7604         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7605         R_FillColors(color4f, 8, cr, cg, cb, ca);
7606         if (r_refdef.fogenabled)
7607         {
7608                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7609                 {
7610                         f1 = RSurf_FogVertex(v);
7611                         f2 = 1 - f1;
7612                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7613                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7614                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7615                 }
7616         }
7617         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7618         R_Mesh_ResetTextureState();
7619         R_SetupShader_Generic_NoTexture(false, false);
7620         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7621 }
7622
7623 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7624 {
7625         prvm_prog_t *prog = SVVM_prog;
7626         int i;
7627         float color[4];
7628         prvm_edict_t *edict;
7629
7630         // this function draws bounding boxes of server entities
7631         if (!sv.active)
7632                 return;
7633
7634         GL_CullFace(GL_NONE);
7635         R_SetupShader_Generic_NoTexture(false, false);
7636
7637         for (i = 0;i < numsurfaces;i++)
7638         {
7639                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7640                 switch ((int)PRVM_serveredictfloat(edict, solid))
7641                 {
7642                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7643                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7644                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7645                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7646                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7647                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7648                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7649                 }
7650                 color[3] *= r_showbboxes.value;
7651                 color[3] = bound(0, color[3], 1);
7652                 GL_DepthTest(!r_showdisabledepthtest.integer);
7653                 GL_CullFace(r_refdef.view.cullface_front);
7654                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7655         }
7656 }
7657
7658 static void R_DrawEntityBBoxes(void)
7659 {
7660         int i;
7661         prvm_edict_t *edict;
7662         vec3_t center;
7663         prvm_prog_t *prog = SVVM_prog;
7664
7665         // this function draws bounding boxes of server entities
7666         if (!sv.active)
7667                 return;
7668
7669         for (i = 0;i < prog->num_edicts;i++)
7670         {
7671                 edict = PRVM_EDICT_NUM(i);
7672                 if (edict->priv.server->free)
7673                         continue;
7674                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7675                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7676                         continue;
7677                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7678                         continue;
7679                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7680                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7681         }
7682 }
7683
7684 static const int nomodelelement3i[24] =
7685 {
7686         5, 2, 0,
7687         5, 1, 2,
7688         5, 0, 3,
7689         5, 3, 1,
7690         0, 2, 4,
7691         2, 1, 4,
7692         3, 0, 4,
7693         1, 3, 4
7694 };
7695
7696 static const unsigned short nomodelelement3s[24] =
7697 {
7698         5, 2, 0,
7699         5, 1, 2,
7700         5, 0, 3,
7701         5, 3, 1,
7702         0, 2, 4,
7703         2, 1, 4,
7704         3, 0, 4,
7705         1, 3, 4
7706 };
7707
7708 static const float nomodelvertex3f[6*3] =
7709 {
7710         -16,   0,   0,
7711          16,   0,   0,
7712           0, -16,   0,
7713           0,  16,   0,
7714           0,   0, -16,
7715           0,   0,  16
7716 };
7717
7718 static const float nomodelcolor4f[6*4] =
7719 {
7720         0.0f, 0.0f, 0.5f, 1.0f,
7721         0.0f, 0.0f, 0.5f, 1.0f,
7722         0.0f, 0.5f, 0.0f, 1.0f,
7723         0.0f, 0.5f, 0.0f, 1.0f,
7724         0.5f, 0.0f, 0.0f, 1.0f,
7725         0.5f, 0.0f, 0.0f, 1.0f
7726 };
7727
7728 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7729 {
7730         int i;
7731         float f1, f2, *c;
7732         float color4f[6*4];
7733
7734         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);
7735
7736         // this is only called once per entity so numsurfaces is always 1, and
7737         // surfacelist is always {0}, so this code does not handle batches
7738
7739         if (rsurface.ent_flags & RENDER_ADDITIVE)
7740         {
7741                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7742                 GL_DepthMask(false);
7743         }
7744         else if (rsurface.colormod[3] < 1)
7745         {
7746                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7747                 GL_DepthMask(false);
7748         }
7749         else
7750         {
7751                 GL_BlendFunc(GL_ONE, GL_ZERO);
7752                 GL_DepthMask(true);
7753         }
7754         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7755         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7756         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7757         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7758         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7759         for (i = 0, c = color4f;i < 6;i++, c += 4)
7760         {
7761                 c[0] *= rsurface.colormod[0];
7762                 c[1] *= rsurface.colormod[1];
7763                 c[2] *= rsurface.colormod[2];
7764                 c[3] *= rsurface.colormod[3];
7765         }
7766         if (r_refdef.fogenabled)
7767         {
7768                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7769                 {
7770                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7771                         f2 = 1 - f1;
7772                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7773                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7774                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7775                 }
7776         }
7777 //      R_Mesh_ResetTextureState();
7778         R_SetupShader_Generic_NoTexture(false, false);
7779         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7780         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7781 }
7782
7783 void R_DrawNoModel(entity_render_t *ent)
7784 {
7785         vec3_t org;
7786         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7787         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7788                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7789         else
7790                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7791 }
7792
7793 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7794 {
7795         vec3_t right1, right2, diff, normal;
7796
7797         VectorSubtract (org2, org1, normal);
7798
7799         // calculate 'right' vector for start
7800         VectorSubtract (r_refdef.view.origin, org1, diff);
7801         CrossProduct (normal, diff, right1);
7802         VectorNormalize (right1);
7803
7804         // calculate 'right' vector for end
7805         VectorSubtract (r_refdef.view.origin, org2, diff);
7806         CrossProduct (normal, diff, right2);
7807         VectorNormalize (right2);
7808
7809         vert[ 0] = org1[0] + width * right1[0];
7810         vert[ 1] = org1[1] + width * right1[1];
7811         vert[ 2] = org1[2] + width * right1[2];
7812         vert[ 3] = org1[0] - width * right1[0];
7813         vert[ 4] = org1[1] - width * right1[1];
7814         vert[ 5] = org1[2] - width * right1[2];
7815         vert[ 6] = org2[0] - width * right2[0];
7816         vert[ 7] = org2[1] - width * right2[1];
7817         vert[ 8] = org2[2] - width * right2[2];
7818         vert[ 9] = org2[0] + width * right2[0];
7819         vert[10] = org2[1] + width * right2[1];
7820         vert[11] = org2[2] + width * right2[2];
7821 }
7822
7823 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)
7824 {
7825         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7826         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7827         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7828         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7829         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7830         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7831         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7832         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7833         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7834         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7835         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7836         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7837 }
7838
7839 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7840 {
7841         int i;
7842         float *vertex3f;
7843         float v[3];
7844         VectorSet(v, x, y, z);
7845         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7846                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7847                         break;
7848         if (i == mesh->numvertices)
7849         {
7850                 if (mesh->numvertices < mesh->maxvertices)
7851                 {
7852                         VectorCopy(v, vertex3f);
7853                         mesh->numvertices++;
7854                 }
7855                 return mesh->numvertices;
7856         }
7857         else
7858                 return i;
7859 }
7860
7861 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7862 {
7863         int i;
7864         int *e, element[3];
7865         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7866         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7867         e = mesh->element3i + mesh->numtriangles * 3;
7868         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7869         {
7870                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7871                 if (mesh->numtriangles < mesh->maxtriangles)
7872                 {
7873                         *e++ = element[0];
7874                         *e++ = element[1];
7875                         *e++ = element[2];
7876                         mesh->numtriangles++;
7877                 }
7878                 element[1] = element[2];
7879         }
7880 }
7881
7882 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7883 {
7884         int i;
7885         int *e, element[3];
7886         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7887         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7888         e = mesh->element3i + mesh->numtriangles * 3;
7889         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7890         {
7891                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7892                 if (mesh->numtriangles < mesh->maxtriangles)
7893                 {
7894                         *e++ = element[0];
7895                         *e++ = element[1];
7896                         *e++ = element[2];
7897                         mesh->numtriangles++;
7898                 }
7899                 element[1] = element[2];
7900         }
7901 }
7902
7903 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7904 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7905 {
7906         int planenum, planenum2;
7907         int w;
7908         int tempnumpoints;
7909         mplane_t *plane, *plane2;
7910         double maxdist;
7911         double temppoints[2][256*3];
7912         // figure out how large a bounding box we need to properly compute this brush
7913         maxdist = 0;
7914         for (w = 0;w < numplanes;w++)
7915                 maxdist = max(maxdist, fabs(planes[w].dist));
7916         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7917         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7918         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7919         {
7920                 w = 0;
7921                 tempnumpoints = 4;
7922                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7923                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7924                 {
7925                         if (planenum2 == planenum)
7926                                 continue;
7927                         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);
7928                         w = !w;
7929                 }
7930                 if (tempnumpoints < 3)
7931                         continue;
7932                 // generate elements forming a triangle fan for this polygon
7933                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7934         }
7935 }
7936
7937 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)
7938 {
7939         texturelayer_t *layer;
7940         layer = t->currentlayers + t->currentnumlayers++;
7941         layer->type = type;
7942         layer->depthmask = depthmask;
7943         layer->blendfunc1 = blendfunc1;
7944         layer->blendfunc2 = blendfunc2;
7945         layer->texture = texture;
7946         layer->texmatrix = *matrix;
7947         layer->color[0] = r;
7948         layer->color[1] = g;
7949         layer->color[2] = b;
7950         layer->color[3] = a;
7951 }
7952
7953 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7954 {
7955         if(parms[0] == 0 && parms[1] == 0)
7956                 return false;
7957         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7958                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7959                         return false;
7960         return true;
7961 }
7962
7963 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7964 {
7965         double index, f;
7966         index = parms[2] + rsurface.shadertime * parms[3];
7967         index -= floor(index);
7968         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7969         {
7970         default:
7971         case Q3WAVEFUNC_NONE:
7972         case Q3WAVEFUNC_NOISE:
7973         case Q3WAVEFUNC_COUNT:
7974                 f = 0;
7975                 break;
7976         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7977         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7978         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7979         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7980         case Q3WAVEFUNC_TRIANGLE:
7981                 index *= 4;
7982                 f = index - floor(index);
7983                 if (index < 1)
7984                 {
7985                         // f = f;
7986                 }
7987                 else if (index < 2)
7988                         f = 1 - f;
7989                 else if (index < 3)
7990                         f = -f;
7991                 else
7992                         f = -(1 - f);
7993                 break;
7994         }
7995         f = parms[0] + parms[1] * f;
7996         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7997                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7998         return (float) f;
7999 }
8000
8001 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8002 {
8003         int w, h, idx;
8004         float shadertime;
8005         float f;
8006         float offsetd[2];
8007         float tcmat[12];
8008         matrix4x4_t matrix, temp;
8009         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8010         // it's better to have one huge fixup every 9 hours than gradual
8011         // degradation over time which looks consistently bad after many hours.
8012         //
8013         // tcmod scroll in particular suffers from this degradation which can't be
8014         // effectively worked around even with floor() tricks because we don't
8015         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8016         // a workaround involving floor() would be incorrect anyway...
8017         shadertime = rsurface.shadertime;
8018         if (shadertime >= 32768.0f)
8019                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8020         switch(tcmod->tcmod)
8021         {
8022                 case Q3TCMOD_COUNT:
8023                 case Q3TCMOD_NONE:
8024                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8025                                 matrix = r_waterscrollmatrix;
8026                         else
8027                                 matrix = identitymatrix;
8028                         break;
8029                 case Q3TCMOD_ENTITYTRANSLATE:
8030                         // this is used in Q3 to allow the gamecode to control texcoord
8031                         // scrolling on the entity, which is not supported in darkplaces yet.
8032                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8033                         break;
8034                 case Q3TCMOD_ROTATE:
8035                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8036                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8037                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8038                         break;
8039                 case Q3TCMOD_SCALE:
8040                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8041                         break;
8042                 case Q3TCMOD_SCROLL:
8043                         // this particular tcmod is a "bug for bug" compatible one with regards to
8044                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8045                         // specifically did the wrapping and so we must mimic that...
8046                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8047                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8048                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8049                         break;
8050                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8051                         w = (int) tcmod->parms[0];
8052                         h = (int) tcmod->parms[1];
8053                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8054                         f = f - floor(f);
8055                         idx = (int) floor(f * w * h);
8056                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8057                         break;
8058                 case Q3TCMOD_STRETCH:
8059                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8060                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8061                         break;
8062                 case Q3TCMOD_TRANSFORM:
8063                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8064                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8065                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8066                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8067                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8068                         break;
8069                 case Q3TCMOD_TURBULENT:
8070                         // this is handled in the RSurf_PrepareVertices function
8071                         matrix = identitymatrix;
8072                         break;
8073         }
8074         temp = *texmatrix;
8075         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8076 }
8077
8078 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8079 {
8080         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8081         char name[MAX_QPATH];
8082         skinframe_t *skinframe;
8083         unsigned char pixels[296*194];
8084         strlcpy(cache->name, skinname, sizeof(cache->name));
8085         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8086         if (developer_loading.integer)
8087                 Con_Printf("loading %s\n", name);
8088         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8089         if (!skinframe || !skinframe->base)
8090         {
8091                 unsigned char *f;
8092                 fs_offset_t filesize;
8093                 skinframe = NULL;
8094                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8095                 if (f)
8096                 {
8097                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8098                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8099                         Mem_Free(f);
8100                 }
8101         }
8102         cache->skinframe = skinframe;
8103 }
8104
8105 texture_t *R_GetCurrentTexture(texture_t *t)
8106 {
8107         int i;
8108         const entity_render_t *ent = rsurface.entity;
8109         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8110         q3shaderinfo_layer_tcmod_t *tcmod;
8111
8112         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8113                 return t->currentframe;
8114         t->update_lastrenderframe = r_textureframe;
8115         t->update_lastrenderentity = (void *)ent;
8116
8117         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8118                 t->camera_entity = ent->entitynumber;
8119         else
8120                 t->camera_entity = 0;
8121
8122         // switch to an alternate material if this is a q1bsp animated material
8123         {
8124                 texture_t *texture = t;
8125                 int s = rsurface.ent_skinnum;
8126                 if ((unsigned int)s >= (unsigned int)model->numskins)
8127                         s = 0;
8128                 if (model->skinscenes)
8129                 {
8130                         if (model->skinscenes[s].framecount > 1)
8131                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8132                         else
8133                                 s = model->skinscenes[s].firstframe;
8134                 }
8135                 if (s > 0)
8136                         t = t + s * model->num_surfaces;
8137                 if (t->animated)
8138                 {
8139                         // use an alternate animation if the entity's frame is not 0,
8140                         // and only if the texture has an alternate animation
8141                         if (rsurface.ent_alttextures && t->anim_total[1])
8142                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8143                         else
8144                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8145                 }
8146                 texture->currentframe = t;
8147         }
8148
8149         // update currentskinframe to be a qw skin or animation frame
8150         if (rsurface.ent_qwskin >= 0)
8151         {
8152                 i = rsurface.ent_qwskin;
8153                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8154                 {
8155                         r_qwskincache_size = cl.maxclients;
8156                         if (r_qwskincache)
8157                                 Mem_Free(r_qwskincache);
8158                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8159                 }
8160                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8161                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8162                 t->currentskinframe = r_qwskincache[i].skinframe;
8163                 if (t->currentskinframe == NULL)
8164                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8165         }
8166         else if (t->numskinframes >= 2)
8167                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8168         if (t->backgroundnumskinframes >= 2)
8169                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8170
8171         t->currentmaterialflags = t->basematerialflags;
8172         t->currentalpha = rsurface.colormod[3];
8173         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8174                 t->currentalpha *= r_wateralpha.value;
8175         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8176                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8177         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8178                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8179         if (!(rsurface.ent_flags & RENDER_LIGHT))
8180                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8181         else if (FAKELIGHT_ENABLED)
8182         {
8183                 // no modellight if using fakelight for the map
8184         }
8185         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8186         {
8187                 // pick a model lighting mode
8188                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8189                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8190                 else
8191                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8192         }
8193         if (rsurface.ent_flags & RENDER_ADDITIVE)
8194                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8195         else if (t->currentalpha < 1)
8196                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8197         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8198         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8199                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8200         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8201                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8202         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8203                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8204         if (t->backgroundnumskinframes)
8205                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8206         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8207         {
8208                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8209                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8210         }
8211         else
8212                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8213         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8214         {
8215                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8216                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8217         }
8218         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8219                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8220
8221         // there is no tcmod
8222         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8223         {
8224                 t->currenttexmatrix = r_waterscrollmatrix;
8225                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8226         }
8227         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8228         {
8229                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8230                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8231         }
8232
8233         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8234                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8235         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8236                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8237
8238         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8239         if (t->currentskinframe->qpixels)
8240                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8241         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8242         if (!t->basetexture)
8243                 t->basetexture = r_texture_notexture;
8244         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8245         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8246         t->nmaptexture = t->currentskinframe->nmap;
8247         if (!t->nmaptexture)
8248                 t->nmaptexture = r_texture_blanknormalmap;
8249         t->glosstexture = r_texture_black;
8250         t->glowtexture = t->currentskinframe->glow;
8251         t->fogtexture = t->currentskinframe->fog;
8252         t->reflectmasktexture = t->currentskinframe->reflect;
8253         if (t->backgroundnumskinframes)
8254         {
8255                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8256                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8257                 t->backgroundglosstexture = r_texture_black;
8258                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8259                 if (!t->backgroundnmaptexture)
8260                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8261                 // make sure that if glow is going to be used, both textures are not NULL
8262                 if (!t->backgroundglowtexture && t->glowtexture)
8263                         t->backgroundglowtexture = r_texture_black;
8264                 if (!t->glowtexture && t->backgroundglowtexture)
8265                         t->glowtexture = r_texture_black;
8266         }
8267         else
8268         {
8269                 t->backgroundbasetexture = r_texture_white;
8270                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8271                 t->backgroundglosstexture = r_texture_black;
8272                 t->backgroundglowtexture = NULL;
8273         }
8274         t->specularpower = r_shadow_glossexponent.value;
8275         // TODO: store reference values for these in the texture?
8276         t->specularscale = 0;
8277         if (r_shadow_gloss.integer > 0)
8278         {
8279                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8280                 {
8281                         if (r_shadow_glossintensity.value > 0)
8282                         {
8283                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8284                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8285                                 t->specularscale = r_shadow_glossintensity.value;
8286                         }
8287                 }
8288                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8289                 {
8290                         t->glosstexture = r_texture_white;
8291                         t->backgroundglosstexture = r_texture_white;
8292                         t->specularscale = r_shadow_gloss2intensity.value;
8293                         t->specularpower = r_shadow_gloss2exponent.value;
8294                 }
8295         }
8296         t->specularscale *= t->specularscalemod;
8297         t->specularpower *= t->specularpowermod;
8298         t->rtlightambient = 0;
8299
8300         // lightmaps mode looks bad with dlights using actual texturing, so turn
8301         // off the colormap and glossmap, but leave the normalmap on as it still
8302         // accurately represents the shading involved
8303         if (gl_lightmaps.integer)
8304         {
8305                 t->basetexture = r_texture_grey128;
8306                 t->pantstexture = r_texture_black;
8307                 t->shirttexture = r_texture_black;
8308                 if (gl_lightmaps.integer < 2)
8309                         t->nmaptexture = r_texture_blanknormalmap;
8310                 t->glosstexture = r_texture_black;
8311                 t->glowtexture = NULL;
8312                 t->fogtexture = NULL;
8313                 t->reflectmasktexture = NULL;
8314                 t->backgroundbasetexture = NULL;
8315                 if (gl_lightmaps.integer < 2)
8316                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8317                 t->backgroundglosstexture = r_texture_black;
8318                 t->backgroundglowtexture = NULL;
8319                 t->specularscale = 0;
8320                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8321         }
8322
8323         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8324         VectorClear(t->dlightcolor);
8325         t->currentnumlayers = 0;
8326         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8327         {
8328                 int blendfunc1, blendfunc2;
8329                 qboolean depthmask;
8330                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8331                 {
8332                         blendfunc1 = GL_SRC_ALPHA;
8333                         blendfunc2 = GL_ONE;
8334                 }
8335                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8336                 {
8337                         blendfunc1 = GL_SRC_ALPHA;
8338                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8339                 }
8340                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8341                 {
8342                         blendfunc1 = t->customblendfunc[0];
8343                         blendfunc2 = t->customblendfunc[1];
8344                 }
8345                 else
8346                 {
8347                         blendfunc1 = GL_ONE;
8348                         blendfunc2 = GL_ZERO;
8349                 }
8350                 // don't colormod evilblend textures
8351                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8352                         VectorSet(t->lightmapcolor, 1, 1, 1);
8353                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8354                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8355                 {
8356                         // fullbright is not affected by r_refdef.lightmapintensity
8357                         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]);
8358                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8359                                 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]);
8360                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8361                                 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]);
8362                 }
8363                 else
8364                 {
8365                         vec3_t ambientcolor;
8366                         float colorscale;
8367                         // set the color tint used for lights affecting this surface
8368                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8369                         colorscale = 2;
8370                         // q3bsp has no lightmap updates, so the lightstylevalue that
8371                         // would normally be baked into the lightmap must be
8372                         // applied to the color
8373                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8374                         if (model->type == mod_brushq3)
8375                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8376                         colorscale *= r_refdef.lightmapintensity;
8377                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8378                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8379                         // basic lit geometry
8380                         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]);
8381                         // add pants/shirt if needed
8382                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8383                                 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]);
8384                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8385                                 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]);
8386                         // now add ambient passes if needed
8387                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8388                         {
8389                                 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]);
8390                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8391                                         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]);
8392                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8393                                         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]);
8394                         }
8395                 }
8396                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8397                         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]);
8398                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8399                 {
8400                         // if this is opaque use alpha blend which will darken the earlier
8401                         // passes cheaply.
8402                         //
8403                         // if this is an alpha blended material, all the earlier passes
8404                         // were darkened by fog already, so we only need to add the fog
8405                         // color ontop through the fog mask texture
8406                         //
8407                         // if this is an additive blended material, all the earlier passes
8408                         // were darkened by fog already, and we should not add fog color
8409                         // (because the background was not darkened, there is no fog color
8410                         // that was lost behind it).
8411                         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]);
8412                 }
8413         }
8414
8415         return t->currentframe;
8416 }
8417
8418 rsurfacestate_t rsurface;
8419
8420 void RSurf_ActiveWorldEntity(void)
8421 {
8422         dp_model_t *model = r_refdef.scene.worldmodel;
8423         //if (rsurface.entity == r_refdef.scene.worldentity)
8424         //      return;
8425         rsurface.entity = r_refdef.scene.worldentity;
8426         rsurface.skeleton = NULL;
8427         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8428         rsurface.ent_skinnum = 0;
8429         rsurface.ent_qwskin = -1;
8430         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8431         rsurface.shadertime = r_refdef.scene.time;
8432         rsurface.matrix = identitymatrix;
8433         rsurface.inversematrix = identitymatrix;
8434         rsurface.matrixscale = 1;
8435         rsurface.inversematrixscale = 1;
8436         R_EntityMatrix(&identitymatrix);
8437         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8438         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8439         rsurface.fograngerecip = r_refdef.fograngerecip;
8440         rsurface.fogheightfade = r_refdef.fogheightfade;
8441         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8442         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8443         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8444         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8445         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8446         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8447         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8448         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8449         rsurface.colormod[3] = 1;
8450         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);
8451         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8452         rsurface.frameblend[0].lerp = 1;
8453         rsurface.ent_alttextures = false;
8454         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8455         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8456         rsurface.entityskeletaltransform3x4 = NULL;
8457         rsurface.entityskeletaltransform3x4buffer = NULL;
8458         rsurface.entityskeletaltransform3x4offset = 0;
8459         rsurface.entityskeletaltransform3x4size = 0;;
8460         rsurface.entityskeletalnumtransforms = 0;
8461         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8462         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8463         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8464         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8465         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8466         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8467         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8468         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8469         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8470         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8471         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8472         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8473         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8474         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8475         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8476         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8477         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8478         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8479         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8480         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8481         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8482         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8483         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8484         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8485         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8486         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8487         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8488         rsurface.modelelement3i = model->surfmesh.data_element3i;
8489         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8490         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8491         rsurface.modelelement3s = model->surfmesh.data_element3s;
8492         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8493         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8494         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8495         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8496         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8497         rsurface.modelsurfaces = model->data_surfaces;
8498         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8499         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8500         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8501         rsurface.modelgeneratedvertex = false;
8502         rsurface.batchgeneratedvertex = false;
8503         rsurface.batchfirstvertex = 0;
8504         rsurface.batchnumvertices = 0;
8505         rsurface.batchfirsttriangle = 0;
8506         rsurface.batchnumtriangles = 0;
8507         rsurface.batchvertex3f  = NULL;
8508         rsurface.batchvertex3f_vertexbuffer = NULL;
8509         rsurface.batchvertex3f_bufferoffset = 0;
8510         rsurface.batchsvector3f = NULL;
8511         rsurface.batchsvector3f_vertexbuffer = NULL;
8512         rsurface.batchsvector3f_bufferoffset = 0;
8513         rsurface.batchtvector3f = NULL;
8514         rsurface.batchtvector3f_vertexbuffer = NULL;
8515         rsurface.batchtvector3f_bufferoffset = 0;
8516         rsurface.batchnormal3f  = NULL;
8517         rsurface.batchnormal3f_vertexbuffer = NULL;
8518         rsurface.batchnormal3f_bufferoffset = 0;
8519         rsurface.batchlightmapcolor4f = NULL;
8520         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8521         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8522         rsurface.batchtexcoordtexture2f = NULL;
8523         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8524         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8525         rsurface.batchtexcoordlightmap2f = NULL;
8526         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8527         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8528         rsurface.batchskeletalindex4ub = NULL;
8529         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8530         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8531         rsurface.batchskeletalweight4ub = NULL;
8532         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8533         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8534         rsurface.batchvertexmesh = NULL;
8535         rsurface.batchvertexmesh_vertexbuffer = NULL;
8536         rsurface.batchvertexmesh_bufferoffset = 0;
8537         rsurface.batchelement3i = NULL;
8538         rsurface.batchelement3i_indexbuffer = NULL;
8539         rsurface.batchelement3i_bufferoffset = 0;
8540         rsurface.batchelement3s = NULL;
8541         rsurface.batchelement3s_indexbuffer = NULL;
8542         rsurface.batchelement3s_bufferoffset = 0;
8543         rsurface.passcolor4f = NULL;
8544         rsurface.passcolor4f_vertexbuffer = NULL;
8545         rsurface.passcolor4f_bufferoffset = 0;
8546         rsurface.forcecurrenttextureupdate = false;
8547 }
8548
8549 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8550 {
8551         dp_model_t *model = ent->model;
8552         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8553         //      return;
8554         rsurface.entity = (entity_render_t *)ent;
8555         rsurface.skeleton = ent->skeleton;
8556         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8557         rsurface.ent_skinnum = ent->skinnum;
8558         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;
8559         rsurface.ent_flags = ent->flags;
8560         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8561         rsurface.matrix = ent->matrix;
8562         rsurface.inversematrix = ent->inversematrix;
8563         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8564         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8565         R_EntityMatrix(&rsurface.matrix);
8566         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8567         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8568         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8569         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8570         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8571         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8572         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8573         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8574         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8575         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8576         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8577         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8578         rsurface.colormod[3] = ent->alpha;
8579         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8580         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8581         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8582         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8583         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8584         if (ent->model->brush.submodel && !prepass)
8585         {
8586                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8587                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8588         }
8589         // if the animcache code decided it should use the shader path, skip the deform step
8590         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8591         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8592         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8593         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8594         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8595         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8596         {
8597                 if (ent->animcache_vertex3f)
8598                 {
8599                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8600                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8601                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8602                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8603                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8604                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8605                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8606                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8607                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8608                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8609                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8610                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8611                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8612                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8613                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8614                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8615                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8616                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8617                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8618                 }
8619                 else if (wanttangents)
8620                 {
8621                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8622                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8623                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8624                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8625                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8626                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8627                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8628                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8629                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8630                         rsurface.modelvertexmesh = NULL;
8631                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8632                         rsurface.modelvertexmesh_bufferoffset = 0;
8633                         rsurface.modelvertex3f_vertexbuffer = NULL;
8634                         rsurface.modelvertex3f_bufferoffset = 0;
8635                         rsurface.modelvertex3f_vertexbuffer = 0;
8636                         rsurface.modelvertex3f_bufferoffset = 0;
8637                         rsurface.modelsvector3f_vertexbuffer = 0;
8638                         rsurface.modelsvector3f_bufferoffset = 0;
8639                         rsurface.modeltvector3f_vertexbuffer = 0;
8640                         rsurface.modeltvector3f_bufferoffset = 0;
8641                         rsurface.modelnormal3f_vertexbuffer = 0;
8642                         rsurface.modelnormal3f_bufferoffset = 0;
8643                 }
8644                 else if (wantnormals)
8645                 {
8646                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8647                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8648                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8649                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8650                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8651                         rsurface.modelsvector3f = NULL;
8652                         rsurface.modeltvector3f = NULL;
8653                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8654                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8655                         rsurface.modelvertexmesh = NULL;
8656                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8657                         rsurface.modelvertexmesh_bufferoffset = 0;
8658                         rsurface.modelvertex3f_vertexbuffer = NULL;
8659                         rsurface.modelvertex3f_bufferoffset = 0;
8660                         rsurface.modelvertex3f_vertexbuffer = 0;
8661                         rsurface.modelvertex3f_bufferoffset = 0;
8662                         rsurface.modelsvector3f_vertexbuffer = 0;
8663                         rsurface.modelsvector3f_bufferoffset = 0;
8664                         rsurface.modeltvector3f_vertexbuffer = 0;
8665                         rsurface.modeltvector3f_bufferoffset = 0;
8666                         rsurface.modelnormal3f_vertexbuffer = 0;
8667                         rsurface.modelnormal3f_bufferoffset = 0;
8668                 }
8669                 else
8670                 {
8671                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8672                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8673                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8674                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8675                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8676                         rsurface.modelsvector3f = NULL;
8677                         rsurface.modeltvector3f = NULL;
8678                         rsurface.modelnormal3f = NULL;
8679                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8680                         rsurface.modelvertexmesh = NULL;
8681                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8682                         rsurface.modelvertexmesh_bufferoffset = 0;
8683                         rsurface.modelvertex3f_vertexbuffer = NULL;
8684                         rsurface.modelvertex3f_bufferoffset = 0;
8685                         rsurface.modelvertex3f_vertexbuffer = 0;
8686                         rsurface.modelvertex3f_bufferoffset = 0;
8687                         rsurface.modelsvector3f_vertexbuffer = 0;
8688                         rsurface.modelsvector3f_bufferoffset = 0;
8689                         rsurface.modeltvector3f_vertexbuffer = 0;
8690                         rsurface.modeltvector3f_bufferoffset = 0;
8691                         rsurface.modelnormal3f_vertexbuffer = 0;
8692                         rsurface.modelnormal3f_bufferoffset = 0;
8693                 }
8694                 rsurface.modelgeneratedvertex = true;
8695         }
8696         else
8697         {
8698                 if (rsurface.entityskeletaltransform3x4)
8699                 {
8700                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8701                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8702                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8703                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8704                 }
8705                 else
8706                 {
8707                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8708                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8709                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8710                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8711                 }
8712                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8713                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8714                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8715                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8716                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8717                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8718                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8719                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8720                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8721                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8722                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8723                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8724                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8725                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8726                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8727                 rsurface.modelgeneratedvertex = false;
8728         }
8729         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8730         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8731         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8732         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8733         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8734         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8735         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8736         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8737         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8738         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8739         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8740         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8741         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8742         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8743         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8744         rsurface.modelelement3i = model->surfmesh.data_element3i;
8745         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8746         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8747         rsurface.modelelement3s = model->surfmesh.data_element3s;
8748         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8749         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8750         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8751         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8752         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8753         rsurface.modelsurfaces = model->data_surfaces;
8754         rsurface.batchgeneratedvertex = false;
8755         rsurface.batchfirstvertex = 0;
8756         rsurface.batchnumvertices = 0;
8757         rsurface.batchfirsttriangle = 0;
8758         rsurface.batchnumtriangles = 0;
8759         rsurface.batchvertex3f  = NULL;
8760         rsurface.batchvertex3f_vertexbuffer = NULL;
8761         rsurface.batchvertex3f_bufferoffset = 0;
8762         rsurface.batchsvector3f = NULL;
8763         rsurface.batchsvector3f_vertexbuffer = NULL;
8764         rsurface.batchsvector3f_bufferoffset = 0;
8765         rsurface.batchtvector3f = NULL;
8766         rsurface.batchtvector3f_vertexbuffer = NULL;
8767         rsurface.batchtvector3f_bufferoffset = 0;
8768         rsurface.batchnormal3f  = NULL;
8769         rsurface.batchnormal3f_vertexbuffer = NULL;
8770         rsurface.batchnormal3f_bufferoffset = 0;
8771         rsurface.batchlightmapcolor4f = NULL;
8772         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8773         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8774         rsurface.batchtexcoordtexture2f = NULL;
8775         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8776         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8777         rsurface.batchtexcoordlightmap2f = NULL;
8778         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8779         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8780         rsurface.batchskeletalindex4ub = NULL;
8781         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8782         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8783         rsurface.batchskeletalweight4ub = NULL;
8784         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8785         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8786         rsurface.batchvertexmesh = NULL;
8787         rsurface.batchvertexmesh_vertexbuffer = NULL;
8788         rsurface.batchvertexmesh_bufferoffset = 0;
8789         rsurface.batchelement3i = NULL;
8790         rsurface.batchelement3i_indexbuffer = NULL;
8791         rsurface.batchelement3i_bufferoffset = 0;
8792         rsurface.batchelement3s = NULL;
8793         rsurface.batchelement3s_indexbuffer = NULL;
8794         rsurface.batchelement3s_bufferoffset = 0;
8795         rsurface.passcolor4f = NULL;
8796         rsurface.passcolor4f_vertexbuffer = NULL;
8797         rsurface.passcolor4f_bufferoffset = 0;
8798         rsurface.forcecurrenttextureupdate = false;
8799 }
8800
8801 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)
8802 {
8803         rsurface.entity = r_refdef.scene.worldentity;
8804         rsurface.skeleton = NULL;
8805         rsurface.ent_skinnum = 0;
8806         rsurface.ent_qwskin = -1;
8807         rsurface.ent_flags = entflags;
8808         rsurface.shadertime = r_refdef.scene.time - shadertime;
8809         rsurface.modelnumvertices = numvertices;
8810         rsurface.modelnumtriangles = numtriangles;
8811         rsurface.matrix = *matrix;
8812         rsurface.inversematrix = *inversematrix;
8813         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8814         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8815         R_EntityMatrix(&rsurface.matrix);
8816         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8817         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8818         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8819         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8820         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8821         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8822         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8823         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8824         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8825         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8826         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8827         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8828         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);
8829         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8830         rsurface.frameblend[0].lerp = 1;
8831         rsurface.ent_alttextures = false;
8832         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8833         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8834         rsurface.entityskeletaltransform3x4 = NULL;
8835         rsurface.entityskeletaltransform3x4buffer = NULL;
8836         rsurface.entityskeletaltransform3x4offset = 0;
8837         rsurface.entityskeletaltransform3x4size = 0;
8838         rsurface.entityskeletalnumtransforms = 0;
8839         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8840         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8841         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8842         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8843         if (wanttangents)
8844         {
8845                 rsurface.modelvertex3f = (float *)vertex3f;
8846                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8847                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8848                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8849         }
8850         else if (wantnormals)
8851         {
8852                 rsurface.modelvertex3f = (float *)vertex3f;
8853                 rsurface.modelsvector3f = NULL;
8854                 rsurface.modeltvector3f = NULL;
8855                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8856         }
8857         else
8858         {
8859                 rsurface.modelvertex3f = (float *)vertex3f;
8860                 rsurface.modelsvector3f = NULL;
8861                 rsurface.modeltvector3f = NULL;
8862                 rsurface.modelnormal3f = NULL;
8863         }
8864         rsurface.modelvertexmesh = NULL;
8865         rsurface.modelvertexmesh_vertexbuffer = NULL;
8866         rsurface.modelvertexmesh_bufferoffset = 0;
8867         rsurface.modelvertex3f_vertexbuffer = 0;
8868         rsurface.modelvertex3f_bufferoffset = 0;
8869         rsurface.modelsvector3f_vertexbuffer = 0;
8870         rsurface.modelsvector3f_bufferoffset = 0;
8871         rsurface.modeltvector3f_vertexbuffer = 0;
8872         rsurface.modeltvector3f_bufferoffset = 0;
8873         rsurface.modelnormal3f_vertexbuffer = 0;
8874         rsurface.modelnormal3f_bufferoffset = 0;
8875         rsurface.modelgeneratedvertex = true;
8876         rsurface.modellightmapcolor4f  = (float *)color4f;
8877         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8878         rsurface.modellightmapcolor4f_bufferoffset = 0;
8879         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8880         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8881         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8882         rsurface.modeltexcoordlightmap2f  = NULL;
8883         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8884         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8885         rsurface.modelskeletalindex4ub = NULL;
8886         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8887         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8888         rsurface.modelskeletalweight4ub = NULL;
8889         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8890         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8891         rsurface.modelelement3i = (int *)element3i;
8892         rsurface.modelelement3i_indexbuffer = NULL;
8893         rsurface.modelelement3i_bufferoffset = 0;
8894         rsurface.modelelement3s = (unsigned short *)element3s;
8895         rsurface.modelelement3s_indexbuffer = NULL;
8896         rsurface.modelelement3s_bufferoffset = 0;
8897         rsurface.modellightmapoffsets = NULL;
8898         rsurface.modelsurfaces = NULL;
8899         rsurface.batchgeneratedvertex = false;
8900         rsurface.batchfirstvertex = 0;
8901         rsurface.batchnumvertices = 0;
8902         rsurface.batchfirsttriangle = 0;
8903         rsurface.batchnumtriangles = 0;
8904         rsurface.batchvertex3f  = NULL;
8905         rsurface.batchvertex3f_vertexbuffer = NULL;
8906         rsurface.batchvertex3f_bufferoffset = 0;
8907         rsurface.batchsvector3f = NULL;
8908         rsurface.batchsvector3f_vertexbuffer = NULL;
8909         rsurface.batchsvector3f_bufferoffset = 0;
8910         rsurface.batchtvector3f = NULL;
8911         rsurface.batchtvector3f_vertexbuffer = NULL;
8912         rsurface.batchtvector3f_bufferoffset = 0;
8913         rsurface.batchnormal3f  = NULL;
8914         rsurface.batchnormal3f_vertexbuffer = NULL;
8915         rsurface.batchnormal3f_bufferoffset = 0;
8916         rsurface.batchlightmapcolor4f = NULL;
8917         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8918         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8919         rsurface.batchtexcoordtexture2f = NULL;
8920         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8921         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8922         rsurface.batchtexcoordlightmap2f = NULL;
8923         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8924         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8925         rsurface.batchskeletalindex4ub = NULL;
8926         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8927         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8928         rsurface.batchskeletalweight4ub = NULL;
8929         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8930         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8931         rsurface.batchvertexmesh = NULL;
8932         rsurface.batchvertexmesh_vertexbuffer = NULL;
8933         rsurface.batchvertexmesh_bufferoffset = 0;
8934         rsurface.batchelement3i = NULL;
8935         rsurface.batchelement3i_indexbuffer = NULL;
8936         rsurface.batchelement3i_bufferoffset = 0;
8937         rsurface.batchelement3s = NULL;
8938         rsurface.batchelement3s_indexbuffer = NULL;
8939         rsurface.batchelement3s_bufferoffset = 0;
8940         rsurface.passcolor4f = NULL;
8941         rsurface.passcolor4f_vertexbuffer = NULL;
8942         rsurface.passcolor4f_bufferoffset = 0;
8943         rsurface.forcecurrenttextureupdate = true;
8944
8945         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8946         {
8947                 if ((wantnormals || wanttangents) && !normal3f)
8948                 {
8949                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8950                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8951                 }
8952                 if (wanttangents && !svector3f)
8953                 {
8954                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8955                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8956                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8957                 }
8958         }
8959 }
8960
8961 float RSurf_FogPoint(const float *v)
8962 {
8963         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8964         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8965         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8966         float FogHeightFade = r_refdef.fogheightfade;
8967         float fogfrac;
8968         unsigned int fogmasktableindex;
8969         if (r_refdef.fogplaneviewabove)
8970                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8971         else
8972                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8973         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8974         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8975 }
8976
8977 float RSurf_FogVertex(const float *v)
8978 {
8979         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8980         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8981         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8982         float FogHeightFade = rsurface.fogheightfade;
8983         float fogfrac;
8984         unsigned int fogmasktableindex;
8985         if (r_refdef.fogplaneviewabove)
8986                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8987         else
8988                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8989         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8990         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8991 }
8992
8993 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8994 {
8995         int i;
8996         for (i = 0;i < numelements;i++)
8997                 outelement3i[i] = inelement3i[i] + adjust;
8998 }
8999
9000 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9001 extern cvar_t gl_vbo;
9002 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9003 {
9004         int deformindex;
9005         int firsttriangle;
9006         int numtriangles;
9007         int firstvertex;
9008         int endvertex;
9009         int numvertices;
9010         int surfacefirsttriangle;
9011         int surfacenumtriangles;
9012         int surfacefirstvertex;
9013         int surfaceendvertex;
9014         int surfacenumvertices;
9015         int batchnumsurfaces = texturenumsurfaces;
9016         int batchnumvertices;
9017         int batchnumtriangles;
9018         int needsupdate;
9019         int i, j;
9020         qboolean gaps;
9021         qboolean dynamicvertex;
9022         float amplitude;
9023         float animpos;
9024         float scale;
9025         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9026         float waveparms[4];
9027         unsigned char *ub;
9028         q3shaderinfo_deform_t *deform;
9029         const msurface_t *surface, *firstsurface;
9030         r_vertexmesh_t *vertexmesh;
9031         if (!texturenumsurfaces)
9032                 return;
9033         // find vertex range of this surface batch
9034         gaps = false;
9035         firstsurface = texturesurfacelist[0];
9036         firsttriangle = firstsurface->num_firsttriangle;
9037         batchnumvertices = 0;
9038         batchnumtriangles = 0;
9039         firstvertex = endvertex = firstsurface->num_firstvertex;
9040         for (i = 0;i < texturenumsurfaces;i++)
9041         {
9042                 surface = texturesurfacelist[i];
9043                 if (surface != firstsurface + i)
9044                         gaps = true;
9045                 surfacefirstvertex = surface->num_firstvertex;
9046                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9047                 surfacenumvertices = surface->num_vertices;
9048                 surfacenumtriangles = surface->num_triangles;
9049                 if (firstvertex > surfacefirstvertex)
9050                         firstvertex = surfacefirstvertex;
9051                 if (endvertex < surfaceendvertex)
9052                         endvertex = surfaceendvertex;
9053                 batchnumvertices += surfacenumvertices;
9054                 batchnumtriangles += surfacenumtriangles;
9055         }
9056
9057         r_refdef.stats[r_stat_batch_batches]++;
9058         if (gaps)
9059                 r_refdef.stats[r_stat_batch_withgaps]++;
9060         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9061         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9062         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9063
9064         // we now know the vertex range used, and if there are any gaps in it
9065         rsurface.batchfirstvertex = firstvertex;
9066         rsurface.batchnumvertices = endvertex - firstvertex;
9067         rsurface.batchfirsttriangle = firsttriangle;
9068         rsurface.batchnumtriangles = batchnumtriangles;
9069
9070         // this variable holds flags for which properties have been updated that
9071         // may require regenerating vertexmesh array...
9072         needsupdate = 0;
9073
9074         // check if any dynamic vertex processing must occur
9075         dynamicvertex = false;
9076
9077         // a cvar to force the dynamic vertex path to be taken, for debugging
9078         if (r_batch_debugdynamicvertexpath.integer)
9079         {
9080                 if (!dynamicvertex)
9081                 {
9082                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9083                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9084                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9085                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9086                 }
9087                 dynamicvertex = true;
9088         }
9089
9090         // if there is a chance of animated vertex colors, it's a dynamic batch
9091         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9092         {
9093                 if (!dynamicvertex)
9094                 {
9095                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9096                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9097                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9098                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9099                 }
9100                 dynamicvertex = true;
9101                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9102         }
9103
9104         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9105         {
9106                 switch (deform->deform)
9107                 {
9108                 default:
9109                 case Q3DEFORM_PROJECTIONSHADOW:
9110                 case Q3DEFORM_TEXT0:
9111                 case Q3DEFORM_TEXT1:
9112                 case Q3DEFORM_TEXT2:
9113                 case Q3DEFORM_TEXT3:
9114                 case Q3DEFORM_TEXT4:
9115                 case Q3DEFORM_TEXT5:
9116                 case Q3DEFORM_TEXT6:
9117                 case Q3DEFORM_TEXT7:
9118                 case Q3DEFORM_NONE:
9119                         break;
9120                 case Q3DEFORM_AUTOSPRITE:
9121                         if (!dynamicvertex)
9122                         {
9123                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9124                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9125                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9126                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9127                         }
9128                         dynamicvertex = true;
9129                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9130                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9131                         break;
9132                 case Q3DEFORM_AUTOSPRITE2:
9133                         if (!dynamicvertex)
9134                         {
9135                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9136                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9137                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9138                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9139                         }
9140                         dynamicvertex = true;
9141                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9142                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9143                         break;
9144                 case Q3DEFORM_NORMAL:
9145                         if (!dynamicvertex)
9146                         {
9147                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9148                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9149                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9150                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9151                         }
9152                         dynamicvertex = true;
9153                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9154                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9155                         break;
9156                 case Q3DEFORM_WAVE:
9157                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9158                                 break; // if wavefunc is a nop, ignore this transform
9159                         if (!dynamicvertex)
9160                         {
9161                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9162                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9163                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9164                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9165                         }
9166                         dynamicvertex = true;
9167                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9168                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9169                         break;
9170                 case Q3DEFORM_BULGE:
9171                         if (!dynamicvertex)
9172                         {
9173                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9174                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9175                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9176                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9177                         }
9178                         dynamicvertex = true;
9179                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9180                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9181                         break;
9182                 case Q3DEFORM_MOVE:
9183                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9184                                 break; // if wavefunc is a nop, ignore this transform
9185                         if (!dynamicvertex)
9186                         {
9187                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9188                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9189                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9190                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9191                         }
9192                         dynamicvertex = true;
9193                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9194                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9195                         break;
9196                 }
9197         }
9198         switch(rsurface.texture->tcgen.tcgen)
9199         {
9200         default:
9201         case Q3TCGEN_TEXTURE:
9202                 break;
9203         case Q3TCGEN_LIGHTMAP:
9204                 if (!dynamicvertex)
9205                 {
9206                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9207                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9208                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9209                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9210                 }
9211                 dynamicvertex = true;
9212                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9213                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9214                 break;
9215         case Q3TCGEN_VECTOR:
9216                 if (!dynamicvertex)
9217                 {
9218                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9219                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9220                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9221                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9222                 }
9223                 dynamicvertex = true;
9224                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9225                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9226                 break;
9227         case Q3TCGEN_ENVIRONMENT:
9228                 if (!dynamicvertex)
9229                 {
9230                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9231                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9232                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9233                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9234                 }
9235                 dynamicvertex = true;
9236                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9237                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9238                 break;
9239         }
9240         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9241         {
9242                 if (!dynamicvertex)
9243                 {
9244                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9245                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9246                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9247                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9248                 }
9249                 dynamicvertex = true;
9250                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9251                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9252         }
9253
9254         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9255         {
9256                 if (!dynamicvertex)
9257                 {
9258                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9259                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9260                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9261                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9262                 }
9263                 dynamicvertex = true;
9264                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9265         }
9266
9267         // when the model data has no vertex buffer (dynamic mesh), we need to
9268         // eliminate gaps
9269         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9270                 batchneed |= BATCHNEED_NOGAPS;
9271
9272         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9273         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9274         // we ensure this by treating the vertex batch as dynamic...
9275         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9276         {
9277                 if (!dynamicvertex)
9278                 {
9279                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9280                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9281                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9282                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9283                 }
9284                 dynamicvertex = true;
9285         }
9286
9287         if (dynamicvertex)
9288         {
9289                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9290                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9291                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9292                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9293                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9294                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9295                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9296                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9297         }
9298
9299         // if needsupdate, we have to do a dynamic vertex batch for sure
9300         if (needsupdate & batchneed)
9301         {
9302                 if (!dynamicvertex)
9303                 {
9304                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9305                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9306                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9307                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9308                 }
9309                 dynamicvertex = true;
9310         }
9311
9312         // see if we need to build vertexmesh from arrays
9313         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9314         {
9315                 if (!dynamicvertex)
9316                 {
9317                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9318                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9319                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9320                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9321                 }
9322                 dynamicvertex = true;
9323         }
9324
9325         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9326         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9327                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9328
9329         rsurface.batchvertex3f = rsurface.modelvertex3f;
9330         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9331         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9332         rsurface.batchsvector3f = rsurface.modelsvector3f;
9333         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9334         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9335         rsurface.batchtvector3f = rsurface.modeltvector3f;
9336         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9337         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9338         rsurface.batchnormal3f = rsurface.modelnormal3f;
9339         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9340         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9341         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9342         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9343         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9344         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9345         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9346         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9347         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9348         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9349         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9350         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9351         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9352         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9353         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9354         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9355         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9356         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9357         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9358         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9359         rsurface.batchelement3i = rsurface.modelelement3i;
9360         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9361         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9362         rsurface.batchelement3s = rsurface.modelelement3s;
9363         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9364         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9365         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9366         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9367         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9368         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9369         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9370
9371         // if any dynamic vertex processing has to occur in software, we copy the
9372         // entire surface list together before processing to rebase the vertices
9373         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9374         //
9375         // if any gaps exist and we do not have a static vertex buffer, we have to
9376         // copy the surface list together to avoid wasting upload bandwidth on the
9377         // vertices in the gaps.
9378         //
9379         // if gaps exist and we have a static vertex buffer, we can choose whether
9380         // to combine the index buffer ranges into one dynamic index buffer or
9381         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9382         //
9383         // in many cases the batch is reduced to one draw call.
9384
9385         rsurface.batchmultidraw = false;
9386         rsurface.batchmultidrawnumsurfaces = 0;
9387         rsurface.batchmultidrawsurfacelist = NULL;
9388
9389         if (!dynamicvertex)
9390         {
9391                 // static vertex data, just set pointers...
9392                 rsurface.batchgeneratedvertex = false;
9393                 // if there are gaps, we want to build a combined index buffer,
9394                 // otherwise use the original static buffer with an appropriate offset
9395                 if (gaps)
9396                 {
9397                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9398                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9399                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9400                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9401                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9402                         {
9403                                 rsurface.batchmultidraw = true;
9404                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9405                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9406                                 return;
9407                         }
9408                         // build a new triangle elements array for this batch
9409                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9410                         rsurface.batchfirsttriangle = 0;
9411                         numtriangles = 0;
9412                         for (i = 0;i < texturenumsurfaces;i++)
9413                         {
9414                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9415                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9416                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9417                                 numtriangles += surfacenumtriangles;
9418                         }
9419                         rsurface.batchelement3i_indexbuffer = NULL;
9420                         rsurface.batchelement3i_bufferoffset = 0;
9421                         rsurface.batchelement3s = NULL;
9422                         rsurface.batchelement3s_indexbuffer = NULL;
9423                         rsurface.batchelement3s_bufferoffset = 0;
9424                         if (endvertex <= 65536)
9425                         {
9426                                 // make a 16bit (unsigned short) index array if possible
9427                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9428                                 for (i = 0;i < numtriangles*3;i++)
9429                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9430                         }
9431                         // upload buffer data for the copytriangles batch
9432                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9433                         {
9434                                 if (rsurface.batchelement3s)
9435                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9436                                 else if (rsurface.batchelement3i)
9437                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9438                         }
9439                 }
9440                 else
9441                 {
9442                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9443                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9444                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9445                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9446                 }
9447                 return;
9448         }
9449
9450         // something needs software processing, do it for real...
9451         // we only directly handle separate array data in this case and then
9452         // generate interleaved data if needed...
9453         rsurface.batchgeneratedvertex = true;
9454         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9455         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9456         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9457         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9458
9459         // now copy the vertex data into a combined array and make an index array
9460         // (this is what Quake3 does all the time)
9461         // we also apply any skeletal animation here that would have been done in
9462         // the vertex shader, because most of the dynamic vertex animation cases
9463         // need actual vertex positions and normals
9464         //if (dynamicvertex)
9465         {
9466                 rsurface.batchvertexmesh = NULL;
9467                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9468                 rsurface.batchvertexmesh_bufferoffset = 0;
9469                 rsurface.batchvertex3f = NULL;
9470                 rsurface.batchvertex3f_vertexbuffer = NULL;
9471                 rsurface.batchvertex3f_bufferoffset = 0;
9472                 rsurface.batchsvector3f = NULL;
9473                 rsurface.batchsvector3f_vertexbuffer = NULL;
9474                 rsurface.batchsvector3f_bufferoffset = 0;
9475                 rsurface.batchtvector3f = NULL;
9476                 rsurface.batchtvector3f_vertexbuffer = NULL;
9477                 rsurface.batchtvector3f_bufferoffset = 0;
9478                 rsurface.batchnormal3f = NULL;
9479                 rsurface.batchnormal3f_vertexbuffer = NULL;
9480                 rsurface.batchnormal3f_bufferoffset = 0;
9481                 rsurface.batchlightmapcolor4f = NULL;
9482                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9483                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9484                 rsurface.batchtexcoordtexture2f = NULL;
9485                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9486                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9487                 rsurface.batchtexcoordlightmap2f = NULL;
9488                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9489                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9490                 rsurface.batchskeletalindex4ub = NULL;
9491                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9492                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9493                 rsurface.batchskeletalweight4ub = NULL;
9494                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9495                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9496                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9497                 rsurface.batchelement3i_indexbuffer = NULL;
9498                 rsurface.batchelement3i_bufferoffset = 0;
9499                 rsurface.batchelement3s = NULL;
9500                 rsurface.batchelement3s_indexbuffer = NULL;
9501                 rsurface.batchelement3s_bufferoffset = 0;
9502                 rsurface.batchskeletaltransform3x4buffer = NULL;
9503                 rsurface.batchskeletaltransform3x4offset = 0;
9504                 rsurface.batchskeletaltransform3x4size = 0;
9505                 // we'll only be setting up certain arrays as needed
9506                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9507                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9508                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9509                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9510                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9511                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9512                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9513                 {
9514                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9515                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9516                 }
9517                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9518                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9519                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9520                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9521                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9522                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9523                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9524                 {
9525                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9526                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9527                 }
9528                 numvertices = 0;
9529                 numtriangles = 0;
9530                 for (i = 0;i < texturenumsurfaces;i++)
9531                 {
9532                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9533                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9534                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9535                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9536                         // copy only the data requested
9537                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9538                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9539                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9540                         {
9541                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9542                                 {
9543                                         if (rsurface.batchvertex3f)
9544                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9545                                         else
9546                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9547                                 }
9548                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9549                                 {
9550                                         if (rsurface.modelnormal3f)
9551                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9552                                         else
9553                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9554                                 }
9555                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9556                                 {
9557                                         if (rsurface.modelsvector3f)
9558                                         {
9559                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9560                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9561                                         }
9562                                         else
9563                                         {
9564                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9565                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9566                                         }
9567                                 }
9568                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9569                                 {
9570                                         if (rsurface.modellightmapcolor4f)
9571                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9572                                         else
9573                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9574                                 }
9575                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9576                                 {
9577                                         if (rsurface.modeltexcoordtexture2f)
9578                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9579                                         else
9580                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9581                                 }
9582                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9583                                 {
9584                                         if (rsurface.modeltexcoordlightmap2f)
9585                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9586                                         else
9587                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9588                                 }
9589                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9590                                 {
9591                                         if (rsurface.modelskeletalindex4ub)
9592                                         {
9593                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9594                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9595                                         }
9596                                         else
9597                                         {
9598                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9599                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9600                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9601                                                 for (j = 0;j < surfacenumvertices;j++)
9602                                                         ub[j*4] = 255;
9603                                         }
9604                                 }
9605                         }
9606                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9607                         numvertices += surfacenumvertices;
9608                         numtriangles += surfacenumtriangles;
9609                 }
9610
9611                 // generate a 16bit index array as well if possible
9612                 // (in general, dynamic batches fit)
9613                 if (numvertices <= 65536)
9614                 {
9615                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9616                         for (i = 0;i < numtriangles*3;i++)
9617                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9618                 }
9619
9620                 // since we've copied everything, the batch now starts at 0
9621                 rsurface.batchfirstvertex = 0;
9622                 rsurface.batchnumvertices = batchnumvertices;
9623                 rsurface.batchfirsttriangle = 0;
9624                 rsurface.batchnumtriangles = batchnumtriangles;
9625         }
9626
9627         // apply skeletal animation that would have been done in the vertex shader
9628         if (rsurface.batchskeletaltransform3x4)
9629         {
9630                 const unsigned char *si;
9631                 const unsigned char *sw;
9632                 const float *t[4];
9633                 const float *b = rsurface.batchskeletaltransform3x4;
9634                 float *vp, *vs, *vt, *vn;
9635                 float w[4];
9636                 float m[3][4], n[3][4];
9637                 float tp[3], ts[3], tt[3], tn[3];
9638                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9639                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9640                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9641                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9642                 si = rsurface.batchskeletalindex4ub;
9643                 sw = rsurface.batchskeletalweight4ub;
9644                 vp = rsurface.batchvertex3f;
9645                 vs = rsurface.batchsvector3f;
9646                 vt = rsurface.batchtvector3f;
9647                 vn = rsurface.batchnormal3f;
9648                 memset(m[0], 0, sizeof(m));
9649                 memset(n[0], 0, sizeof(n));
9650                 for (i = 0;i < batchnumvertices;i++)
9651                 {
9652                         t[0] = b + si[0]*12;
9653                         if (sw[0] == 255)
9654                         {
9655                                 // common case - only one matrix
9656                                 m[0][0] = t[0][ 0];
9657                                 m[0][1] = t[0][ 1];
9658                                 m[0][2] = t[0][ 2];
9659                                 m[0][3] = t[0][ 3];
9660                                 m[1][0] = t[0][ 4];
9661                                 m[1][1] = t[0][ 5];
9662                                 m[1][2] = t[0][ 6];
9663                                 m[1][3] = t[0][ 7];
9664                                 m[2][0] = t[0][ 8];
9665                                 m[2][1] = t[0][ 9];
9666                                 m[2][2] = t[0][10];
9667                                 m[2][3] = t[0][11];
9668                         }
9669                         else if (sw[2] + sw[3])
9670                         {
9671                                 // blend 4 matrices
9672                                 t[1] = b + si[1]*12;
9673                                 t[2] = b + si[2]*12;
9674                                 t[3] = b + si[3]*12;
9675                                 w[0] = sw[0] * (1.0f / 255.0f);
9676                                 w[1] = sw[1] * (1.0f / 255.0f);
9677                                 w[2] = sw[2] * (1.0f / 255.0f);
9678                                 w[3] = sw[3] * (1.0f / 255.0f);
9679                                 // blend the matrices
9680                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9681                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9682                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9683                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9684                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9685                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9686                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9687                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9688                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9689                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9690                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9691                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9692                         }
9693                         else
9694                         {
9695                                 // blend 2 matrices
9696                                 t[1] = b + si[1]*12;
9697                                 w[0] = sw[0] * (1.0f / 255.0f);
9698                                 w[1] = sw[1] * (1.0f / 255.0f);
9699                                 // blend the matrices
9700                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9701                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9702                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9703                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9704                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9705                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9706                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9707                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9708                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9709                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9710                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9711                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9712                         }
9713                         si += 4;
9714                         sw += 4;
9715                         // modify the vertex
9716                         VectorCopy(vp, tp);
9717                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9718                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9719                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9720                         vp += 3;
9721                         if (vn)
9722                         {
9723                                 // the normal transformation matrix is a set of cross products...
9724                                 CrossProduct(m[1], m[2], n[0]);
9725                                 CrossProduct(m[2], m[0], n[1]);
9726                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9727                                 VectorCopy(vn, tn);
9728                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9729                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9730                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9731                                 VectorNormalize(vn);
9732                                 vn += 3;
9733                                 if (vs)
9734                                 {
9735                                         VectorCopy(vs, ts);
9736                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9737                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9738                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9739                                         VectorNormalize(vs);
9740                                         vs += 3;
9741                                         VectorCopy(vt, tt);
9742                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9743                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9744                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9745                                         VectorNormalize(vt);
9746                                         vt += 3;
9747                                 }
9748                         }
9749                 }
9750                 rsurface.batchskeletaltransform3x4 = NULL;
9751                 rsurface.batchskeletalnumtransforms = 0;
9752         }
9753
9754         // q1bsp surfaces rendered in vertex color mode have to have colors
9755         // calculated based on lightstyles
9756         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9757         {
9758                 // generate color arrays for the surfaces in this list
9759                 int c[4];
9760                 int scale;
9761                 int size3;
9762                 const int *offsets;
9763                 const unsigned char *lm;
9764                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9765                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9766                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9767                 numvertices = 0;
9768                 for (i = 0;i < texturenumsurfaces;i++)
9769                 {
9770                         surface = texturesurfacelist[i];
9771                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9772                         surfacenumvertices = surface->num_vertices;
9773                         if (surface->lightmapinfo->samples)
9774                         {
9775                                 for (j = 0;j < surfacenumvertices;j++)
9776                                 {
9777                                         lm = surface->lightmapinfo->samples + offsets[j];
9778                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9779                                         VectorScale(lm, scale, c);
9780                                         if (surface->lightmapinfo->styles[1] != 255)
9781                                         {
9782                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9783                                                 lm += size3;
9784                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9785                                                 VectorMA(c, scale, lm, c);
9786                                                 if (surface->lightmapinfo->styles[2] != 255)
9787                                                 {
9788                                                         lm += size3;
9789                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9790                                                         VectorMA(c, scale, lm, c);
9791                                                         if (surface->lightmapinfo->styles[3] != 255)
9792                                                         {
9793                                                                 lm += size3;
9794                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9795                                                                 VectorMA(c, scale, lm, c);
9796                                                         }
9797                                                 }
9798                                         }
9799                                         c[0] >>= 7;
9800                                         c[1] >>= 7;
9801                                         c[2] >>= 7;
9802                                         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);
9803                                         numvertices++;
9804                                 }
9805                         }
9806                         else
9807                         {
9808                                 for (j = 0;j < surfacenumvertices;j++)
9809                                 {
9810                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9811                                         numvertices++;
9812                                 }
9813                         }
9814                 }
9815         }
9816
9817         // if vertices are deformed (sprite flares and things in maps, possibly
9818         // water waves, bulges and other deformations), modify the copied vertices
9819         // in place
9820         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9821         {
9822                 switch (deform->deform)
9823                 {
9824                 default:
9825                 case Q3DEFORM_PROJECTIONSHADOW:
9826                 case Q3DEFORM_TEXT0:
9827                 case Q3DEFORM_TEXT1:
9828                 case Q3DEFORM_TEXT2:
9829                 case Q3DEFORM_TEXT3:
9830                 case Q3DEFORM_TEXT4:
9831                 case Q3DEFORM_TEXT5:
9832                 case Q3DEFORM_TEXT6:
9833                 case Q3DEFORM_TEXT7:
9834                 case Q3DEFORM_NONE:
9835                         break;
9836                 case Q3DEFORM_AUTOSPRITE:
9837                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9838                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9839                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9840                         VectorNormalize(newforward);
9841                         VectorNormalize(newright);
9842                         VectorNormalize(newup);
9843 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9844 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9845 //                      rsurface.batchvertex3f_bufferoffset = 0;
9846 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9847 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9848 //                      rsurface.batchsvector3f_bufferoffset = 0;
9849 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9850 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9851 //                      rsurface.batchtvector3f_bufferoffset = 0;
9852 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9853 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9854 //                      rsurface.batchnormal3f_bufferoffset = 0;
9855                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9856                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9857                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9858                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9859                                 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);
9860                         // a single autosprite surface can contain multiple sprites...
9861                         for (j = 0;j < batchnumvertices - 3;j += 4)
9862                         {
9863                                 VectorClear(center);
9864                                 for (i = 0;i < 4;i++)
9865                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9866                                 VectorScale(center, 0.25f, center);
9867                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9868                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9869                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9870                                 for (i = 0;i < 4;i++)
9871                                 {
9872                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9873                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9874                                 }
9875                         }
9876                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9877                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9878                         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);
9879                         break;
9880                 case Q3DEFORM_AUTOSPRITE2:
9881                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9882                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9883                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9884                         VectorNormalize(newforward);
9885                         VectorNormalize(newright);
9886                         VectorNormalize(newup);
9887 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9888 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9889 //                      rsurface.batchvertex3f_bufferoffset = 0;
9890                         {
9891                                 const float *v1, *v2;
9892                                 vec3_t start, end;
9893                                 float f, l;
9894                                 struct
9895                                 {
9896                                         float length2;
9897                                         const float *v1;
9898                                         const float *v2;
9899                                 }
9900                                 shortest[2];
9901                                 memset(shortest, 0, sizeof(shortest));
9902                                 // a single autosprite surface can contain multiple sprites...
9903                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9904                                 {
9905                                         VectorClear(center);
9906                                         for (i = 0;i < 4;i++)
9907                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9908                                         VectorScale(center, 0.25f, center);
9909                                         // find the two shortest edges, then use them to define the
9910                                         // axis vectors for rotating around the central axis
9911                                         for (i = 0;i < 6;i++)
9912                                         {
9913                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9914                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9915                                                 l = VectorDistance2(v1, v2);
9916                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9917                                                 if (v1[2] != v2[2])
9918                                                         l += (1.0f / 1024.0f);
9919                                                 if (shortest[0].length2 > l || i == 0)
9920                                                 {
9921                                                         shortest[1] = shortest[0];
9922                                                         shortest[0].length2 = l;
9923                                                         shortest[0].v1 = v1;
9924                                                         shortest[0].v2 = v2;
9925                                                 }
9926                                                 else if (shortest[1].length2 > l || i == 1)
9927                                                 {
9928                                                         shortest[1].length2 = l;
9929                                                         shortest[1].v1 = v1;
9930                                                         shortest[1].v2 = v2;
9931                                                 }
9932                                         }
9933                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9934                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9935                                         // this calculates the right vector from the shortest edge
9936                                         // and the up vector from the edge midpoints
9937                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9938                                         VectorNormalize(right);
9939                                         VectorSubtract(end, start, up);
9940                                         VectorNormalize(up);
9941                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9942                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9943                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9944                                         VectorNegate(forward, forward);
9945                                         VectorReflect(forward, 0, up, forward);
9946                                         VectorNormalize(forward);
9947                                         CrossProduct(up, forward, newright);
9948                                         VectorNormalize(newright);
9949                                         // rotate the quad around the up axis vector, this is made
9950                                         // especially easy by the fact we know the quad is flat,
9951                                         // so we only have to subtract the center position and
9952                                         // measure distance along the right vector, and then
9953                                         // multiply that by the newright vector and add back the
9954                                         // center position
9955                                         // we also need to subtract the old position to undo the
9956                                         // displacement from the center, which we do with a
9957                                         // DotProduct, the subtraction/addition of center is also
9958                                         // optimized into DotProducts here
9959                                         l = DotProduct(right, center);
9960                                         for (i = 0;i < 4;i++)
9961                                         {
9962                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9963                                                 f = DotProduct(right, v1) - l;
9964                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9965                                         }
9966                                 }
9967                         }
9968                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9969                         {
9970 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9971 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9972 //                              rsurface.batchnormal3f_bufferoffset = 0;
9973                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9974                         }
9975                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9976                         {
9977 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9978 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9979 //                              rsurface.batchsvector3f_bufferoffset = 0;
9980 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9981 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9982 //                              rsurface.batchtvector3f_bufferoffset = 0;
9983                                 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);
9984                         }
9985                         break;
9986                 case Q3DEFORM_NORMAL:
9987                         // deform the normals to make reflections wavey
9988                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9989                         rsurface.batchnormal3f_vertexbuffer = NULL;
9990                         rsurface.batchnormal3f_bufferoffset = 0;
9991                         for (j = 0;j < batchnumvertices;j++)
9992                         {
9993                                 float vertex[3];
9994                                 float *normal = rsurface.batchnormal3f + 3*j;
9995                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9996                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9997                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9998                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9999                                 VectorNormalize(normal);
10000                         }
10001                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10002                         {
10003 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10004 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10005 //                              rsurface.batchsvector3f_bufferoffset = 0;
10006 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10007 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10008 //                              rsurface.batchtvector3f_bufferoffset = 0;
10009                                 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);
10010                         }
10011                         break;
10012                 case Q3DEFORM_WAVE:
10013                         // deform vertex array to make wavey water and flags and such
10014                         waveparms[0] = deform->waveparms[0];
10015                         waveparms[1] = deform->waveparms[1];
10016                         waveparms[2] = deform->waveparms[2];
10017                         waveparms[3] = deform->waveparms[3];
10018                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10019                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10020                         // this is how a divisor of vertex influence on deformation
10021                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10022                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10023 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10024 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10025 //                      rsurface.batchvertex3f_bufferoffset = 0;
10026 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10027 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10028 //                      rsurface.batchnormal3f_bufferoffset = 0;
10029                         for (j = 0;j < batchnumvertices;j++)
10030                         {
10031                                 // if the wavefunc depends on time, evaluate it per-vertex
10032                                 if (waveparms[3])
10033                                 {
10034                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10035                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10036                                 }
10037                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10038                         }
10039                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10040                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10041                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10042                         {
10043 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10044 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10045 //                              rsurface.batchsvector3f_bufferoffset = 0;
10046 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10047 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10048 //                              rsurface.batchtvector3f_bufferoffset = 0;
10049                                 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);
10050                         }
10051                         break;
10052                 case Q3DEFORM_BULGE:
10053                         // deform vertex array to make the surface have moving bulges
10054 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10055 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10056 //                      rsurface.batchvertex3f_bufferoffset = 0;
10057 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10058 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10059 //                      rsurface.batchnormal3f_bufferoffset = 0;
10060                         for (j = 0;j < batchnumvertices;j++)
10061                         {
10062                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10063                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10064                         }
10065                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10066                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10067                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10068                         {
10069 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10070 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10071 //                              rsurface.batchsvector3f_bufferoffset = 0;
10072 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10073 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10074 //                              rsurface.batchtvector3f_bufferoffset = 0;
10075                                 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);
10076                         }
10077                         break;
10078                 case Q3DEFORM_MOVE:
10079                         // deform vertex array
10080                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10081                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10082                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10083                         VectorScale(deform->parms, scale, waveparms);
10084 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10085 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10086 //                      rsurface.batchvertex3f_bufferoffset = 0;
10087                         for (j = 0;j < batchnumvertices;j++)
10088                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10089                         break;
10090                 }
10091         }
10092
10093         // generate texcoords based on the chosen texcoord source
10094         switch(rsurface.texture->tcgen.tcgen)
10095         {
10096         default:
10097         case Q3TCGEN_TEXTURE:
10098                 break;
10099         case Q3TCGEN_LIGHTMAP:
10100 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10101 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10102 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10103                 if (rsurface.batchtexcoordlightmap2f)
10104                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10105                 break;
10106         case Q3TCGEN_VECTOR:
10107 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10108 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10109 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10110                 for (j = 0;j < batchnumvertices;j++)
10111                 {
10112                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10113                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10114                 }
10115                 break;
10116         case Q3TCGEN_ENVIRONMENT:
10117                 // make environment reflections using a spheremap
10118                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10119                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10120                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10121                 for (j = 0;j < batchnumvertices;j++)
10122                 {
10123                         // identical to Q3A's method, but executed in worldspace so
10124                         // carried models can be shiny too
10125
10126                         float viewer[3], d, reflected[3], worldreflected[3];
10127
10128                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10129                         // VectorNormalize(viewer);
10130
10131                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10132
10133                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10134                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10135                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10136                         // note: this is proportinal to viewer, so we can normalize later
10137
10138                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10139                         VectorNormalize(worldreflected);
10140
10141                         // note: this sphere map only uses world x and z!
10142                         // so positive and negative y will LOOK THE SAME.
10143                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10144                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10145                 }
10146                 break;
10147         }
10148         // the only tcmod that needs software vertex processing is turbulent, so
10149         // check for it here and apply the changes if needed
10150         // and we only support that as the first one
10151         // (handling a mixture of turbulent and other tcmods would be problematic
10152         //  without punting it entirely to a software path)
10153         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10154         {
10155                 amplitude = rsurface.texture->tcmods[0].parms[1];
10156                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10157 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10158 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10159 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10160                 for (j = 0;j < batchnumvertices;j++)
10161                 {
10162                         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);
10163                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10164                 }
10165         }
10166
10167         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10168         {
10169                 // convert the modified arrays to vertex structs
10170 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10171 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10172 //              rsurface.batchvertexmesh_bufferoffset = 0;
10173                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10174                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10175                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10176                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10177                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10178                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10179                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10180                 {
10181                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10182                         {
10183                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10184                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10185                         }
10186                 }
10187                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10188                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10189                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10190                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10191                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10192                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10193                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10194                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10195                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10196                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10197                 {
10198                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10199                         {
10200                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10201                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10202                         }
10203                 }
10204         }
10205
10206         // upload buffer data for the dynamic batch
10207         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10208         {
10209                 if (rsurface.batchvertexmesh)
10210                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10211                 else
10212                 {
10213                         if (rsurface.batchvertex3f)
10214                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10215                         if (rsurface.batchsvector3f)
10216                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10217                         if (rsurface.batchtvector3f)
10218                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10219                         if (rsurface.batchnormal3f)
10220                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10221                         if (rsurface.batchlightmapcolor4f)
10222                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10223                         if (rsurface.batchtexcoordtexture2f)
10224                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10225                         if (rsurface.batchtexcoordlightmap2f)
10226                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10227                         if (rsurface.batchskeletalindex4ub)
10228                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10229                         if (rsurface.batchskeletalweight4ub)
10230                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10231                 }
10232                 if (rsurface.batchelement3s)
10233                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10234                 else if (rsurface.batchelement3i)
10235                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10236         }
10237 }
10238
10239 void RSurf_DrawBatch(void)
10240 {
10241         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10242         // through the pipeline, killing it earlier in the pipeline would have
10243         // per-surface overhead rather than per-batch overhead, so it's best to
10244         // reject it here, before it hits glDraw.
10245         if (rsurface.batchnumtriangles == 0)
10246                 return;
10247 #if 0
10248         // batch debugging code
10249         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10250         {
10251                 int i;
10252                 int j;
10253                 int c;
10254                 const int *e;
10255                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10256                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10257                 {
10258                         c = e[i];
10259                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10260                         {
10261                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10262                                 {
10263                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10264                                                 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);
10265                                         break;
10266                                 }
10267                         }
10268                 }
10269         }
10270 #endif
10271         if (rsurface.batchmultidraw)
10272         {
10273                 // issue multiple draws rather than copying index data
10274                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10275                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10276                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10277                 for (i = 0;i < numsurfaces;)
10278                 {
10279                         // combine consecutive surfaces as one draw
10280                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10281                                 if (surfacelist[j] != surfacelist[k] + 1)
10282                                         break;
10283                         firstvertex = surfacelist[i]->num_firstvertex;
10284                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10285                         firsttriangle = surfacelist[i]->num_firsttriangle;
10286                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10287                         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);
10288                         i = j;
10289                 }
10290         }
10291         else
10292         {
10293                 // there is only one consecutive run of index data (may have been combined)
10294                 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);
10295         }
10296 }
10297
10298 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10299 {
10300         // pick the closest matching water plane
10301         int planeindex, vertexindex, bestplaneindex = -1;
10302         float d, bestd;
10303         vec3_t vert;
10304         const float *v;
10305         r_waterstate_waterplane_t *p;
10306         qboolean prepared = false;
10307         bestd = 0;
10308         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10309         {
10310                 if(p->camera_entity != rsurface.texture->camera_entity)
10311                         continue;
10312                 d = 0;
10313                 if(!prepared)
10314                 {
10315                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10316                         prepared = true;
10317                         if(rsurface.batchnumvertices == 0)
10318                                 break;
10319                 }
10320                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10321                 {
10322                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10323                         d += fabs(PlaneDiff(vert, &p->plane));
10324                 }
10325                 if (bestd > d || bestplaneindex < 0)
10326                 {
10327                         bestd = d;
10328                         bestplaneindex = planeindex;
10329                 }
10330         }
10331         return bestplaneindex;
10332         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10333         // this situation though, as it might be better to render single larger
10334         // batches with useless stuff (backface culled for example) than to
10335         // render multiple smaller batches
10336 }
10337
10338 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10339 {
10340         int i;
10341         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10342         rsurface.passcolor4f_vertexbuffer = 0;
10343         rsurface.passcolor4f_bufferoffset = 0;
10344         for (i = 0;i < rsurface.batchnumvertices;i++)
10345                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10346 }
10347
10348 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10349 {
10350         int i;
10351         float f;
10352         const float *v;
10353         const float *c;
10354         float *c2;
10355         if (rsurface.passcolor4f)
10356         {
10357                 // generate color arrays
10358                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10359                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10360                 rsurface.passcolor4f_vertexbuffer = 0;
10361                 rsurface.passcolor4f_bufferoffset = 0;
10362                 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)
10363                 {
10364                         f = RSurf_FogVertex(v);
10365                         c2[0] = c[0] * f;
10366                         c2[1] = c[1] * f;
10367                         c2[2] = c[2] * f;
10368                         c2[3] = c[3];
10369                 }
10370         }
10371         else
10372         {
10373                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10374                 rsurface.passcolor4f_vertexbuffer = 0;
10375                 rsurface.passcolor4f_bufferoffset = 0;
10376                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10377                 {
10378                         f = RSurf_FogVertex(v);
10379                         c2[0] = f;
10380                         c2[1] = f;
10381                         c2[2] = f;
10382                         c2[3] = 1;
10383                 }
10384         }
10385 }
10386
10387 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10388 {
10389         int i;
10390         float f;
10391         const float *v;
10392         const float *c;
10393         float *c2;
10394         if (!rsurface.passcolor4f)
10395                 return;
10396         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10397         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10398         rsurface.passcolor4f_vertexbuffer = 0;
10399         rsurface.passcolor4f_bufferoffset = 0;
10400         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)
10401         {
10402                 f = RSurf_FogVertex(v);
10403                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10404                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10405                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10406                 c2[3] = c[3];
10407         }
10408 }
10409
10410 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10411 {
10412         int i;
10413         const float *c;
10414         float *c2;
10415         if (!rsurface.passcolor4f)
10416                 return;
10417         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10418         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10419         rsurface.passcolor4f_vertexbuffer = 0;
10420         rsurface.passcolor4f_bufferoffset = 0;
10421         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10422         {
10423                 c2[0] = c[0] * r;
10424                 c2[1] = c[1] * g;
10425                 c2[2] = c[2] * b;
10426                 c2[3] = c[3] * a;
10427         }
10428 }
10429
10430 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10431 {
10432         int i;
10433         const float *c;
10434         float *c2;
10435         if (!rsurface.passcolor4f)
10436                 return;
10437         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10438         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10439         rsurface.passcolor4f_vertexbuffer = 0;
10440         rsurface.passcolor4f_bufferoffset = 0;
10441         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10442         {
10443                 c2[0] = c[0] + r_refdef.scene.ambient;
10444                 c2[1] = c[1] + r_refdef.scene.ambient;
10445                 c2[2] = c[2] + r_refdef.scene.ambient;
10446                 c2[3] = c[3];
10447         }
10448 }
10449
10450 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10451 {
10452         // TODO: optimize
10453         rsurface.passcolor4f = NULL;
10454         rsurface.passcolor4f_vertexbuffer = 0;
10455         rsurface.passcolor4f_bufferoffset = 0;
10456         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10457         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10458         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10459         GL_Color(r, g, b, a);
10460         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10461         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10462         R_Mesh_TexMatrix(0, NULL);
10463         RSurf_DrawBatch();
10464 }
10465
10466 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10467 {
10468         // TODO: optimize applyfog && applycolor case
10469         // just apply fog if necessary, and tint the fog color array if necessary
10470         rsurface.passcolor4f = NULL;
10471         rsurface.passcolor4f_vertexbuffer = 0;
10472         rsurface.passcolor4f_bufferoffset = 0;
10473         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10474         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10475         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10476         GL_Color(r, g, b, a);
10477         RSurf_DrawBatch();
10478 }
10479
10480 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10481 {
10482         // TODO: optimize
10483         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10484         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10485         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10486         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10487         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10488         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10489         GL_Color(r, g, b, a);
10490         RSurf_DrawBatch();
10491 }
10492
10493 static void RSurf_DrawBatch_GL11_ClampColor(void)
10494 {
10495         int i;
10496         const float *c1;
10497         float *c2;
10498         if (!rsurface.passcolor4f)
10499                 return;
10500         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10501         {
10502                 c2[0] = bound(0.0f, c1[0], 1.0f);
10503                 c2[1] = bound(0.0f, c1[1], 1.0f);
10504                 c2[2] = bound(0.0f, c1[2], 1.0f);
10505                 c2[3] = bound(0.0f, c1[3], 1.0f);
10506         }
10507 }
10508
10509 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10510 {
10511         int i;
10512         float f;
10513         const float *v;
10514         const float *n;
10515         float *c;
10516         //vec3_t eyedir;
10517
10518         // fake shading
10519         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10520         rsurface.passcolor4f_vertexbuffer = 0;
10521         rsurface.passcolor4f_bufferoffset = 0;
10522         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)
10523         {
10524                 f = -DotProduct(r_refdef.view.forward, n);
10525                 f = max(0, f);
10526                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10527                 f *= r_refdef.lightmapintensity;
10528                 Vector4Set(c, f, f, f, 1);
10529         }
10530 }
10531
10532 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10533 {
10534         RSurf_DrawBatch_GL11_ApplyFakeLight();
10535         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10536         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10537         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10538         GL_Color(r, g, b, a);
10539         RSurf_DrawBatch();
10540 }
10541
10542 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10543 {
10544         int i;
10545         float f;
10546         float alpha;
10547         const float *v;
10548         const float *n;
10549         float *c;
10550         vec3_t ambientcolor;
10551         vec3_t diffusecolor;
10552         vec3_t lightdir;
10553         // TODO: optimize
10554         // model lighting
10555         VectorCopy(rsurface.modellight_lightdir, lightdir);
10556         f = 0.5f * r_refdef.lightmapintensity;
10557         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10558         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10559         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10560         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10561         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10562         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10563         alpha = *a;
10564         if (VectorLength2(diffusecolor) > 0)
10565         {
10566                 // q3-style directional shading
10567                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10568                 rsurface.passcolor4f_vertexbuffer = 0;
10569                 rsurface.passcolor4f_bufferoffset = 0;
10570                 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)
10571                 {
10572                         if ((f = DotProduct(n, lightdir)) > 0)
10573                                 VectorMA(ambientcolor, f, diffusecolor, c);
10574                         else
10575                                 VectorCopy(ambientcolor, c);
10576                         c[3] = alpha;
10577                 }
10578                 *r = 1;
10579                 *g = 1;
10580                 *b = 1;
10581                 *a = 1;
10582                 *applycolor = false;
10583         }
10584         else
10585         {
10586                 *r = ambientcolor[0];
10587                 *g = ambientcolor[1];
10588                 *b = ambientcolor[2];
10589                 rsurface.passcolor4f = NULL;
10590                 rsurface.passcolor4f_vertexbuffer = 0;
10591                 rsurface.passcolor4f_bufferoffset = 0;
10592         }
10593 }
10594
10595 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10596 {
10597         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10598         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10599         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10600         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10601         GL_Color(r, g, b, a);
10602         RSurf_DrawBatch();
10603 }
10604
10605 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10606 {
10607         int i;
10608         float f;
10609         const float *v;
10610         float *c;
10611
10612         // fake shading
10613         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10614         rsurface.passcolor4f_vertexbuffer = 0;
10615         rsurface.passcolor4f_bufferoffset = 0;
10616
10617         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10618         {
10619                 f = 1 - RSurf_FogVertex(v);
10620                 c[0] = r;
10621                 c[1] = g;
10622                 c[2] = b;
10623                 c[3] = f * a;
10624         }
10625 }
10626
10627 void RSurf_SetupDepthAndCulling(void)
10628 {
10629         // submodels are biased to avoid z-fighting with world surfaces that they
10630         // may be exactly overlapping (avoids z-fighting artifacts on certain
10631         // doors and things in Quake maps)
10632         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10633         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10634         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10635         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10636 }
10637
10638 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10639 {
10640         // transparent sky would be ridiculous
10641         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10642                 return;
10643         R_SetupShader_Generic_NoTexture(false, false);
10644         skyrenderlater = true;
10645         RSurf_SetupDepthAndCulling();
10646         GL_DepthMask(true);
10647         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10648         // skymasking on them, and Quake3 never did sky masking (unlike
10649         // software Quake and software Quake2), so disable the sky masking
10650         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10651         // and skymasking also looks very bad when noclipping outside the
10652         // level, so don't use it then either.
10653         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10654         {
10655                 R_Mesh_ResetTextureState();
10656                 if (skyrendermasked)
10657                 {
10658                         R_SetupShader_DepthOrShadow(false, false, false);
10659                         // depth-only (masking)
10660                         GL_ColorMask(0,0,0,0);
10661                         // just to make sure that braindead drivers don't draw
10662                         // anything despite that colormask...
10663                         GL_BlendFunc(GL_ZERO, GL_ONE);
10664                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10665                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10666                 }
10667                 else
10668                 {
10669                         R_SetupShader_Generic_NoTexture(false, false);
10670                         // fog sky
10671                         GL_BlendFunc(GL_ONE, GL_ZERO);
10672                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10673                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10674                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10675                 }
10676                 RSurf_DrawBatch();
10677                 if (skyrendermasked)
10678                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10679         }
10680         R_Mesh_ResetTextureState();
10681         GL_Color(1, 1, 1, 1);
10682 }
10683
10684 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10685 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10686 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10687 {
10688         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10689                 return;
10690         if (prepass)
10691         {
10692                 // render screenspace normalmap to texture
10693                 GL_DepthMask(true);
10694                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10695                 RSurf_DrawBatch();
10696                 return;
10697         }
10698
10699         // bind lightmap texture
10700
10701         // water/refraction/reflection/camera surfaces have to be handled specially
10702         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10703         {
10704                 int start, end, startplaneindex;
10705                 for (start = 0;start < texturenumsurfaces;start = end)
10706                 {
10707                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10708                         if(startplaneindex < 0)
10709                         {
10710                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10711                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10712                                 end = start + 1;
10713                                 continue;
10714                         }
10715                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10716                                 ;
10717                         // now that we have a batch using the same planeindex, render it
10718                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10719                         {
10720                                 // render water or distortion background
10721                                 GL_DepthMask(true);
10722                                 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);
10723                                 RSurf_DrawBatch();
10724                                 // blend surface on top
10725                                 GL_DepthMask(false);
10726                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10727                                 RSurf_DrawBatch();
10728                         }
10729                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10730                         {
10731                                 // render surface with reflection texture as input
10732                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10733                                 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);
10734                                 RSurf_DrawBatch();
10735                         }
10736                 }
10737                 return;
10738         }
10739
10740         // render surface batch normally
10741         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10742         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);
10743         RSurf_DrawBatch();
10744 }
10745
10746 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10747 {
10748         // OpenGL 1.3 path - anything not completely ancient
10749         qboolean applycolor;
10750         qboolean applyfog;
10751         int layerindex;
10752         const texturelayer_t *layer;
10753         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);
10754         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10755
10756         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10757         {
10758                 vec4_t layercolor;
10759                 int layertexrgbscale;
10760                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10761                 {
10762                         if (layerindex == 0)
10763                                 GL_AlphaTest(true);
10764                         else
10765                         {
10766                                 GL_AlphaTest(false);
10767                                 GL_DepthFunc(GL_EQUAL);
10768                         }
10769                 }
10770                 GL_DepthMask(layer->depthmask && writedepth);
10771                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10772                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10773                 {
10774                         layertexrgbscale = 4;
10775                         VectorScale(layer->color, 0.25f, layercolor);
10776                 }
10777                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10778                 {
10779                         layertexrgbscale = 2;
10780                         VectorScale(layer->color, 0.5f, layercolor);
10781                 }
10782                 else
10783                 {
10784                         layertexrgbscale = 1;
10785                         VectorScale(layer->color, 1.0f, layercolor);
10786                 }
10787                 layercolor[3] = layer->color[3];
10788                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10789                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10790                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10791                 switch (layer->type)
10792                 {
10793                 case TEXTURELAYERTYPE_LITTEXTURE:
10794                         // single-pass lightmapped texture with 2x rgbscale
10795                         R_Mesh_TexBind(0, r_texture_white);
10796                         R_Mesh_TexMatrix(0, NULL);
10797                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10798                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10799                         R_Mesh_TexBind(1, layer->texture);
10800                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10801                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10802                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10803                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10804                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10805                         else if (FAKELIGHT_ENABLED)
10806                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10807                         else if (rsurface.uselightmaptexture)
10808                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10809                         else
10810                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10811                         break;
10812                 case TEXTURELAYERTYPE_TEXTURE:
10813                         // singletexture unlit texture with transparency support
10814                         R_Mesh_TexBind(0, layer->texture);
10815                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10816                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10817                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10818                         R_Mesh_TexBind(1, 0);
10819                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10820                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10821                         break;
10822                 case TEXTURELAYERTYPE_FOG:
10823                         // singletexture fogging
10824                         if (layer->texture)
10825                         {
10826                                 R_Mesh_TexBind(0, layer->texture);
10827                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10828                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10829                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10830                         }
10831                         else
10832                         {
10833                                 R_Mesh_TexBind(0, 0);
10834                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10835                         }
10836                         R_Mesh_TexBind(1, 0);
10837                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10838                         // generate a color array for the fog pass
10839                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10840                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10841                         RSurf_DrawBatch();
10842                         break;
10843                 default:
10844                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10845                 }
10846         }
10847         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10848         {
10849                 GL_DepthFunc(GL_LEQUAL);
10850                 GL_AlphaTest(false);
10851         }
10852 }
10853
10854 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10855 {
10856         // OpenGL 1.1 - crusty old voodoo path
10857         qboolean applyfog;
10858         int layerindex;
10859         const texturelayer_t *layer;
10860         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);
10861         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10862
10863         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10864         {
10865                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10866                 {
10867                         if (layerindex == 0)
10868                                 GL_AlphaTest(true);
10869                         else
10870                         {
10871                                 GL_AlphaTest(false);
10872                                 GL_DepthFunc(GL_EQUAL);
10873                         }
10874                 }
10875                 GL_DepthMask(layer->depthmask && writedepth);
10876                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10877                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10878                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10879                 switch (layer->type)
10880                 {
10881                 case TEXTURELAYERTYPE_LITTEXTURE:
10882                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10883                         {
10884                                 // two-pass lit texture with 2x rgbscale
10885                                 // first the lightmap pass
10886                                 R_Mesh_TexBind(0, r_texture_white);
10887                                 R_Mesh_TexMatrix(0, NULL);
10888                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10889                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10890                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10891                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10892                                 else if (FAKELIGHT_ENABLED)
10893                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10894                                 else if (rsurface.uselightmaptexture)
10895                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10896                                 else
10897                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10898                                 // then apply the texture to it
10899                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10900                                 R_Mesh_TexBind(0, layer->texture);
10901                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10902                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10903                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10904                                 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);
10905                         }
10906                         else
10907                         {
10908                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10909                                 R_Mesh_TexBind(0, layer->texture);
10910                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10911                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10912                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10913                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10914                                         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);
10915                                 else if (FAKELIGHT_ENABLED)
10916                                         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);
10917                                 else
10918                                         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);
10919                         }
10920                         break;
10921                 case TEXTURELAYERTYPE_TEXTURE:
10922                         // singletexture unlit texture with transparency support
10923                         R_Mesh_TexBind(0, layer->texture);
10924                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10925                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10926                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10927                         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);
10928                         break;
10929                 case TEXTURELAYERTYPE_FOG:
10930                         // singletexture fogging
10931                         if (layer->texture)
10932                         {
10933                                 R_Mesh_TexBind(0, layer->texture);
10934                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10935                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10936                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10937                         }
10938                         else
10939                         {
10940                                 R_Mesh_TexBind(0, 0);
10941                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10942                         }
10943                         // generate a color array for the fog pass
10944                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10945                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10946                         RSurf_DrawBatch();
10947                         break;
10948                 default:
10949                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10950                 }
10951         }
10952         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10953         {
10954                 GL_DepthFunc(GL_LEQUAL);
10955                 GL_AlphaTest(false);
10956         }
10957 }
10958
10959 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10960 {
10961         int vi;
10962         int j;
10963         r_vertexgeneric_t *batchvertex;
10964         float c[4];
10965
10966 //      R_Mesh_ResetTextureState();
10967         R_SetupShader_Generic_NoTexture(false, false);
10968
10969         if(rsurface.texture && rsurface.texture->currentskinframe)
10970         {
10971                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10972                 c[3] *= rsurface.texture->currentalpha;
10973         }
10974         else
10975         {
10976                 c[0] = 1;
10977                 c[1] = 0;
10978                 c[2] = 1;
10979                 c[3] = 1;
10980         }
10981
10982         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10983         {
10984                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10985                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10986                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10987         }
10988
10989         // brighten it up (as texture value 127 means "unlit")
10990         c[0] *= 2 * r_refdef.view.colorscale;
10991         c[1] *= 2 * r_refdef.view.colorscale;
10992         c[2] *= 2 * r_refdef.view.colorscale;
10993
10994         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10995                 c[3] *= r_wateralpha.value;
10996
10997         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10998         {
10999                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11000                 GL_DepthMask(false);
11001         }
11002         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11003         {
11004                 GL_BlendFunc(GL_ONE, GL_ONE);
11005                 GL_DepthMask(false);
11006         }
11007         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11008         {
11009                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11010                 GL_DepthMask(false);
11011         }
11012         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11013         {
11014                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11015                 GL_DepthMask(false);
11016         }
11017         else
11018         {
11019                 GL_BlendFunc(GL_ONE, GL_ZERO);
11020                 GL_DepthMask(writedepth);
11021         }
11022
11023         if (r_showsurfaces.integer == 3)
11024         {
11025                 rsurface.passcolor4f = NULL;
11026
11027                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11028                 {
11029                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11030
11031                         rsurface.passcolor4f = NULL;
11032                         rsurface.passcolor4f_vertexbuffer = 0;
11033                         rsurface.passcolor4f_bufferoffset = 0;
11034                 }
11035                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11036                 {
11037                         qboolean applycolor = true;
11038                         float one = 1.0;
11039
11040                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11041
11042                         r_refdef.lightmapintensity = 1;
11043                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11044                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11045                 }
11046                 else if (FAKELIGHT_ENABLED)
11047                 {
11048                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11049
11050                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11051                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11052                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11053                 }
11054                 else
11055                 {
11056                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11057
11058                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11059                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11060                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11061                 }
11062
11063                 if(!rsurface.passcolor4f)
11064                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11065
11066                 RSurf_DrawBatch_GL11_ApplyAmbient();
11067                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11068                 if(r_refdef.fogenabled)
11069                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11070                 RSurf_DrawBatch_GL11_ClampColor();
11071
11072                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11073                 R_SetupShader_Generic_NoTexture(false, false);
11074                 RSurf_DrawBatch();
11075         }
11076         else if (!r_refdef.view.showdebug)
11077         {
11078                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11079                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11080                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11081                 {
11082                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11083                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11084                 }
11085                 R_Mesh_PrepareVertices_Generic_Unlock();
11086                 RSurf_DrawBatch();
11087         }
11088         else if (r_showsurfaces.integer == 4)
11089         {
11090                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11091                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11092                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11093                 {
11094                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11095                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11096                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11097                 }
11098                 R_Mesh_PrepareVertices_Generic_Unlock();
11099                 RSurf_DrawBatch();
11100         }
11101         else if (r_showsurfaces.integer == 2)
11102         {
11103                 const int *e;
11104                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11105                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11106                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11107                 {
11108                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11109                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11110                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11111                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11112                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11113                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11114                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11115                 }
11116                 R_Mesh_PrepareVertices_Generic_Unlock();
11117                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11118         }
11119         else
11120         {
11121                 int texturesurfaceindex;
11122                 int k;
11123                 const msurface_t *surface;
11124                 float surfacecolor4f[4];
11125                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11126                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11127                 vi = 0;
11128                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11129                 {
11130                         surface = texturesurfacelist[texturesurfaceindex];
11131                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11132                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11133                         for (j = 0;j < surface->num_vertices;j++)
11134                         {
11135                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11136                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11137                                 vi++;
11138                         }
11139                 }
11140                 R_Mesh_PrepareVertices_Generic_Unlock();
11141                 RSurf_DrawBatch();
11142         }
11143 }
11144
11145 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11146 {
11147         CHECKGLERROR
11148         RSurf_SetupDepthAndCulling();
11149         if (r_showsurfaces.integer)
11150         {
11151                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11152                 return;
11153         }
11154         switch (vid.renderpath)
11155         {
11156         case RENDERPATH_GL20:
11157         case RENDERPATH_D3D9:
11158         case RENDERPATH_D3D10:
11159         case RENDERPATH_D3D11:
11160         case RENDERPATH_SOFT:
11161         case RENDERPATH_GLES2:
11162                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11163                 break;
11164         case RENDERPATH_GL13:
11165         case RENDERPATH_GLES1:
11166                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11167                 break;
11168         case RENDERPATH_GL11:
11169                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11170                 break;
11171         }
11172         CHECKGLERROR
11173 }
11174
11175 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11176 {
11177         CHECKGLERROR
11178         RSurf_SetupDepthAndCulling();
11179         if (r_showsurfaces.integer)
11180         {
11181                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11182                 return;
11183         }
11184         switch (vid.renderpath)
11185         {
11186         case RENDERPATH_GL20:
11187         case RENDERPATH_D3D9:
11188         case RENDERPATH_D3D10:
11189         case RENDERPATH_D3D11:
11190         case RENDERPATH_SOFT:
11191         case RENDERPATH_GLES2:
11192                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11193                 break;
11194         case RENDERPATH_GL13:
11195         case RENDERPATH_GLES1:
11196                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11197                 break;
11198         case RENDERPATH_GL11:
11199                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11200                 break;
11201         }
11202         CHECKGLERROR
11203 }
11204
11205 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11206 {
11207         int i, j;
11208         int texturenumsurfaces, endsurface;
11209         texture_t *texture;
11210         const msurface_t *surface;
11211         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11212
11213         // if the model is static it doesn't matter what value we give for
11214         // wantnormals and wanttangents, so this logic uses only rules applicable
11215         // to a model, knowing that they are meaningless otherwise
11216         if (ent == r_refdef.scene.worldentity)
11217                 RSurf_ActiveWorldEntity();
11218         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11219                 RSurf_ActiveModelEntity(ent, false, false, false);
11220         else
11221         {
11222                 switch (vid.renderpath)
11223                 {
11224                 case RENDERPATH_GL20:
11225                 case RENDERPATH_D3D9:
11226                 case RENDERPATH_D3D10:
11227                 case RENDERPATH_D3D11:
11228                 case RENDERPATH_SOFT:
11229                 case RENDERPATH_GLES2:
11230                         RSurf_ActiveModelEntity(ent, true, true, false);
11231                         break;
11232                 case RENDERPATH_GL11:
11233                 case RENDERPATH_GL13:
11234                 case RENDERPATH_GLES1:
11235                         RSurf_ActiveModelEntity(ent, true, false, false);
11236                         break;
11237                 }
11238         }
11239
11240         if (r_transparentdepthmasking.integer)
11241         {
11242                 qboolean setup = false;
11243                 for (i = 0;i < numsurfaces;i = j)
11244                 {
11245                         j = i + 1;
11246                         surface = rsurface.modelsurfaces + surfacelist[i];
11247                         texture = surface->texture;
11248                         rsurface.texture = R_GetCurrentTexture(texture);
11249                         rsurface.lightmaptexture = NULL;
11250                         rsurface.deluxemaptexture = NULL;
11251                         rsurface.uselightmaptexture = false;
11252                         // scan ahead until we find a different texture
11253                         endsurface = min(i + 1024, numsurfaces);
11254                         texturenumsurfaces = 0;
11255                         texturesurfacelist[texturenumsurfaces++] = surface;
11256                         for (;j < endsurface;j++)
11257                         {
11258                                 surface = rsurface.modelsurfaces + surfacelist[j];
11259                                 if (texture != surface->texture)
11260                                         break;
11261                                 texturesurfacelist[texturenumsurfaces++] = surface;
11262                         }
11263                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11264                                 continue;
11265                         // render the range of surfaces as depth
11266                         if (!setup)
11267                         {
11268                                 setup = true;
11269                                 GL_ColorMask(0,0,0,0);
11270                                 GL_Color(1,1,1,1);
11271                                 GL_DepthTest(true);
11272                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11273                                 GL_DepthMask(true);
11274 //                              R_Mesh_ResetTextureState();
11275                         }
11276                         RSurf_SetupDepthAndCulling();
11277                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11278                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11279                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11280                         RSurf_DrawBatch();
11281                 }
11282                 if (setup)
11283                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11284         }
11285
11286         for (i = 0;i < numsurfaces;i = j)
11287         {
11288                 j = i + 1;
11289                 surface = rsurface.modelsurfaces + surfacelist[i];
11290                 texture = surface->texture;
11291                 rsurface.texture = R_GetCurrentTexture(texture);
11292                 // scan ahead until we find a different texture
11293                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11294                 texturenumsurfaces = 0;
11295                 texturesurfacelist[texturenumsurfaces++] = surface;
11296                 if(FAKELIGHT_ENABLED)
11297                 {
11298                         rsurface.lightmaptexture = NULL;
11299                         rsurface.deluxemaptexture = NULL;
11300                         rsurface.uselightmaptexture = false;
11301                         for (;j < endsurface;j++)
11302                         {
11303                                 surface = rsurface.modelsurfaces + surfacelist[j];
11304                                 if (texture != surface->texture)
11305                                         break;
11306                                 texturesurfacelist[texturenumsurfaces++] = surface;
11307                         }
11308                 }
11309                 else
11310                 {
11311                         rsurface.lightmaptexture = surface->lightmaptexture;
11312                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11313                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11314                         for (;j < endsurface;j++)
11315                         {
11316                                 surface = rsurface.modelsurfaces + surfacelist[j];
11317                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11318                                         break;
11319                                 texturesurfacelist[texturenumsurfaces++] = surface;
11320                         }
11321                 }
11322                 // render the range of surfaces
11323                 if (ent == r_refdef.scene.worldentity)
11324                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11325                 else
11326                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11327         }
11328         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11329 }
11330
11331 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11332 {
11333         // transparent surfaces get pushed off into the transparent queue
11334         int surfacelistindex;
11335         const msurface_t *surface;
11336         vec3_t tempcenter, center;
11337         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11338         {
11339                 surface = texturesurfacelist[surfacelistindex];
11340                 if (r_transparent_sortsurfacesbynearest.integer)
11341                 {
11342                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11343                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11344                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11345                 }
11346                 else
11347                 {
11348                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11349                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11350                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11351                 }
11352                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11353                 if (rsurface.entity->transparent_offset) // transparent offset
11354                 {
11355                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11356                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11357                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11358                 }
11359                 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);
11360         }
11361 }
11362
11363 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11364 {
11365         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11366                 return;
11367         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11368                 return;
11369         RSurf_SetupDepthAndCulling();
11370         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11371         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11372         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11373         RSurf_DrawBatch();
11374 }
11375
11376 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11377 {
11378         CHECKGLERROR
11379         if (depthonly)
11380                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11381         else if (prepass)
11382         {
11383                 if (!rsurface.texture->currentnumlayers)
11384                         return;
11385                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11386                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11387                 else
11388                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11389         }
11390         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11391                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11392         else if (!rsurface.texture->currentnumlayers)
11393                 return;
11394         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11395         {
11396                 // in the deferred case, transparent surfaces were queued during prepass
11397                 if (!r_shadow_usingdeferredprepass)
11398                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11399         }
11400         else
11401         {
11402                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11403                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11404         }
11405         CHECKGLERROR
11406 }
11407
11408 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11409 {
11410         int i, j;
11411         texture_t *texture;
11412         R_FrameData_SetMark();
11413         // break the surface list down into batches by texture and use of lightmapping
11414         for (i = 0;i < numsurfaces;i = j)
11415         {
11416                 j = i + 1;
11417                 // texture is the base texture pointer, rsurface.texture is the
11418                 // current frame/skin the texture is directing us to use (for example
11419                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11420                 // use skin 1 instead)
11421                 texture = surfacelist[i]->texture;
11422                 rsurface.texture = R_GetCurrentTexture(texture);
11423                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11424                 {
11425                         // if this texture is not the kind we want, skip ahead to the next one
11426                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11427                                 ;
11428                         continue;
11429                 }
11430                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11431                 {
11432                         rsurface.lightmaptexture = NULL;
11433                         rsurface.deluxemaptexture = NULL;
11434                         rsurface.uselightmaptexture = false;
11435                         // simply scan ahead until we find a different texture or lightmap state
11436                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11437                                 ;
11438                 }
11439                 else
11440                 {
11441                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11442                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11443                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11444                         // simply scan ahead until we find a different texture or lightmap state
11445                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11446                                 ;
11447                 }
11448                 // render the range of surfaces
11449                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11450         }
11451         R_FrameData_ReturnToMark();
11452 }
11453
11454 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11455 {
11456         CHECKGLERROR
11457         if (depthonly)
11458                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11459         else if (prepass)
11460         {
11461                 if (!rsurface.texture->currentnumlayers)
11462                         return;
11463                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11464                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11465                 else
11466                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11467         }
11468         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11469                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11470         else if (!rsurface.texture->currentnumlayers)
11471                 return;
11472         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11473         {
11474                 // in the deferred case, transparent surfaces were queued during prepass
11475                 if (!r_shadow_usingdeferredprepass)
11476                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11477         }
11478         else
11479         {
11480                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11481                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11482         }
11483         CHECKGLERROR
11484 }
11485
11486 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11487 {
11488         int i, j;
11489         texture_t *texture;
11490         R_FrameData_SetMark();
11491         // break the surface list down into batches by texture and use of lightmapping
11492         for (i = 0;i < numsurfaces;i = j)
11493         {
11494                 j = i + 1;
11495                 // texture is the base texture pointer, rsurface.texture is the
11496                 // current frame/skin the texture is directing us to use (for example
11497                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11498                 // use skin 1 instead)
11499                 texture = surfacelist[i]->texture;
11500                 rsurface.texture = R_GetCurrentTexture(texture);
11501                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11502                 {
11503                         // if this texture is not the kind we want, skip ahead to the next one
11504                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11505                                 ;
11506                         continue;
11507                 }
11508                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11509                 {
11510                         rsurface.lightmaptexture = NULL;
11511                         rsurface.deluxemaptexture = NULL;
11512                         rsurface.uselightmaptexture = false;
11513                         // simply scan ahead until we find a different texture or lightmap state
11514                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11515                                 ;
11516                 }
11517                 else
11518                 {
11519                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11520                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11521                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11522                         // simply scan ahead until we find a different texture or lightmap state
11523                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11524                                 ;
11525                 }
11526                 // render the range of surfaces
11527                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11528         }
11529         R_FrameData_ReturnToMark();
11530 }
11531
11532 float locboxvertex3f[6*4*3] =
11533 {
11534         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11535         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11536         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11537         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11538         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11539         1,0,0, 0,0,0, 0,1,0, 1,1,0
11540 };
11541
11542 unsigned short locboxelements[6*2*3] =
11543 {
11544          0, 1, 2, 0, 2, 3,
11545          4, 5, 6, 4, 6, 7,
11546          8, 9,10, 8,10,11,
11547         12,13,14, 12,14,15,
11548         16,17,18, 16,18,19,
11549         20,21,22, 20,22,23
11550 };
11551
11552 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11553 {
11554         int i, j;
11555         cl_locnode_t *loc = (cl_locnode_t *)ent;
11556         vec3_t mins, size;
11557         float vertex3f[6*4*3];
11558         CHECKGLERROR
11559         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11560         GL_DepthMask(false);
11561         GL_DepthRange(0, 1);
11562         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11563         GL_DepthTest(true);
11564         GL_CullFace(GL_NONE);
11565         R_EntityMatrix(&identitymatrix);
11566
11567 //      R_Mesh_ResetTextureState();
11568
11569         i = surfacelist[0];
11570         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11571                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11572                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11573                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11574
11575         if (VectorCompare(loc->mins, loc->maxs))
11576         {
11577                 VectorSet(size, 2, 2, 2);
11578                 VectorMA(loc->mins, -0.5f, size, mins);
11579         }
11580         else
11581         {
11582                 VectorCopy(loc->mins, mins);
11583                 VectorSubtract(loc->maxs, loc->mins, size);
11584         }
11585
11586         for (i = 0;i < 6*4*3;)
11587                 for (j = 0;j < 3;j++, i++)
11588                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11589
11590         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11591         R_SetupShader_Generic_NoTexture(false, false);
11592         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11593 }
11594
11595 void R_DrawLocs(void)
11596 {
11597         int index;
11598         cl_locnode_t *loc, *nearestloc;
11599         vec3_t center;
11600         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11601         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11602         {
11603                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11604                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11605         }
11606 }
11607
11608 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11609 {
11610         if (decalsystem->decals)
11611                 Mem_Free(decalsystem->decals);
11612         memset(decalsystem, 0, sizeof(*decalsystem));
11613 }
11614
11615 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)
11616 {
11617         tridecal_t *decal;
11618         tridecal_t *decals;
11619         int i;
11620
11621         // expand or initialize the system
11622         if (decalsystem->maxdecals <= decalsystem->numdecals)
11623         {
11624                 decalsystem_t old = *decalsystem;
11625                 qboolean useshortelements;
11626                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11627                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11628                 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)));
11629                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11630                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11631                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11632                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11633                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11634                 if (decalsystem->numdecals)
11635                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11636                 if (old.decals)
11637                         Mem_Free(old.decals);
11638                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11639                         decalsystem->element3i[i] = i;
11640                 if (useshortelements)
11641                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11642                                 decalsystem->element3s[i] = i;
11643         }
11644
11645         // grab a decal and search for another free slot for the next one
11646         decals = decalsystem->decals;
11647         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11648         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11649                 ;
11650         decalsystem->freedecal = i;
11651         if (decalsystem->numdecals <= i)
11652                 decalsystem->numdecals = i + 1;
11653
11654         // initialize the decal
11655         decal->lived = 0;
11656         decal->triangleindex = triangleindex;
11657         decal->surfaceindex = surfaceindex;
11658         decal->decalsequence = decalsequence;
11659         decal->color4f[0][0] = c0[0];
11660         decal->color4f[0][1] = c0[1];
11661         decal->color4f[0][2] = c0[2];
11662         decal->color4f[0][3] = 1;
11663         decal->color4f[1][0] = c1[0];
11664         decal->color4f[1][1] = c1[1];
11665         decal->color4f[1][2] = c1[2];
11666         decal->color4f[1][3] = 1;
11667         decal->color4f[2][0] = c2[0];
11668         decal->color4f[2][1] = c2[1];
11669         decal->color4f[2][2] = c2[2];
11670         decal->color4f[2][3] = 1;
11671         decal->vertex3f[0][0] = v0[0];
11672         decal->vertex3f[0][1] = v0[1];
11673         decal->vertex3f[0][2] = v0[2];
11674         decal->vertex3f[1][0] = v1[0];
11675         decal->vertex3f[1][1] = v1[1];
11676         decal->vertex3f[1][2] = v1[2];
11677         decal->vertex3f[2][0] = v2[0];
11678         decal->vertex3f[2][1] = v2[1];
11679         decal->vertex3f[2][2] = v2[2];
11680         decal->texcoord2f[0][0] = t0[0];
11681         decal->texcoord2f[0][1] = t0[1];
11682         decal->texcoord2f[1][0] = t1[0];
11683         decal->texcoord2f[1][1] = t1[1];
11684         decal->texcoord2f[2][0] = t2[0];
11685         decal->texcoord2f[2][1] = t2[1];
11686         TriangleNormal(v0, v1, v2, decal->plane);
11687         VectorNormalize(decal->plane);
11688         decal->plane[3] = DotProduct(v0, decal->plane);
11689 }
11690
11691 extern cvar_t cl_decals_bias;
11692 extern cvar_t cl_decals_models;
11693 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11694 // baseparms, parms, temps
11695 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)
11696 {
11697         int cornerindex;
11698         int index;
11699         float v[9][3];
11700         const float *vertex3f;
11701         const float *normal3f;
11702         int numpoints;
11703         float points[2][9][3];
11704         float temp[3];
11705         float tc[9][2];
11706         float f;
11707         float c[9][4];
11708         const int *e;
11709
11710         e = rsurface.modelelement3i + 3*triangleindex;
11711
11712         vertex3f = rsurface.modelvertex3f;
11713         normal3f = rsurface.modelnormal3f;
11714
11715         if (normal3f)
11716         {
11717                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11718                 {
11719                         index = 3*e[cornerindex];
11720                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11721                 }
11722         }
11723         else
11724         {
11725                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11726                 {
11727                         index = 3*e[cornerindex];
11728                         VectorCopy(vertex3f + index, v[cornerindex]);
11729                 }
11730         }
11731
11732         // cull backfaces
11733         //TriangleNormal(v[0], v[1], v[2], normal);
11734         //if (DotProduct(normal, localnormal) < 0.0f)
11735         //      continue;
11736         // clip by each of the box planes formed from the projection matrix
11737         // if anything survives, we emit the decal
11738         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]);
11739         if (numpoints < 3)
11740                 return;
11741         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]);
11742         if (numpoints < 3)
11743                 return;
11744         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]);
11745         if (numpoints < 3)
11746                 return;
11747         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]);
11748         if (numpoints < 3)
11749                 return;
11750         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]);
11751         if (numpoints < 3)
11752                 return;
11753         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]);
11754         if (numpoints < 3)
11755                 return;
11756         // some part of the triangle survived, so we have to accept it...
11757         if (dynamic)
11758         {
11759                 // dynamic always uses the original triangle
11760                 numpoints = 3;
11761                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11762                 {
11763                         index = 3*e[cornerindex];
11764                         VectorCopy(vertex3f + index, v[cornerindex]);
11765                 }
11766         }
11767         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11768         {
11769                 // convert vertex positions to texcoords
11770                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11771                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11772                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11773                 // calculate distance fade from the projection origin
11774                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11775                 f = bound(0.0f, f, 1.0f);
11776                 c[cornerindex][0] = r * f;
11777                 c[cornerindex][1] = g * f;
11778                 c[cornerindex][2] = b * f;
11779                 c[cornerindex][3] = 1.0f;
11780                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11781         }
11782         if (dynamic)
11783                 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);
11784         else
11785                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11786                         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);
11787 }
11788 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)
11789 {
11790         matrix4x4_t projection;
11791         decalsystem_t *decalsystem;
11792         qboolean dynamic;
11793         dp_model_t *model;
11794         const msurface_t *surface;
11795         const msurface_t *surfaces;
11796         const int *surfacelist;
11797         const texture_t *texture;
11798         int numtriangles;
11799         int numsurfacelist;
11800         int surfacelistindex;
11801         int surfaceindex;
11802         int triangleindex;
11803         float localorigin[3];
11804         float localnormal[3];
11805         float localmins[3];
11806         float localmaxs[3];
11807         float localsize;
11808         //float normal[3];
11809         float planes[6][4];
11810         float angles[3];
11811         bih_t *bih;
11812         int bih_triangles_count;
11813         int bih_triangles[256];
11814         int bih_surfaces[256];
11815
11816         decalsystem = &ent->decalsystem;
11817         model = ent->model;
11818         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11819         {
11820                 R_DecalSystem_Reset(&ent->decalsystem);
11821                 return;
11822         }
11823
11824         if (!model->brush.data_leafs && !cl_decals_models.integer)
11825         {
11826                 if (decalsystem->model)
11827                         R_DecalSystem_Reset(decalsystem);
11828                 return;
11829         }
11830
11831         if (decalsystem->model != model)
11832                 R_DecalSystem_Reset(decalsystem);
11833         decalsystem->model = model;
11834
11835         RSurf_ActiveModelEntity(ent, true, false, false);
11836
11837         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11838         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11839         VectorNormalize(localnormal);
11840         localsize = worldsize*rsurface.inversematrixscale;
11841         localmins[0] = localorigin[0] - localsize;
11842         localmins[1] = localorigin[1] - localsize;
11843         localmins[2] = localorigin[2] - localsize;
11844         localmaxs[0] = localorigin[0] + localsize;
11845         localmaxs[1] = localorigin[1] + localsize;
11846         localmaxs[2] = localorigin[2] + localsize;
11847
11848         //VectorCopy(localnormal, planes[4]);
11849         //VectorVectors(planes[4], planes[2], planes[0]);
11850         AnglesFromVectors(angles, localnormal, NULL, false);
11851         AngleVectors(angles, planes[0], planes[2], planes[4]);
11852         VectorNegate(planes[0], planes[1]);
11853         VectorNegate(planes[2], planes[3]);
11854         VectorNegate(planes[4], planes[5]);
11855         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11856         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11857         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11858         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11859         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11860         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11861
11862 #if 1
11863 // works
11864 {
11865         matrix4x4_t forwardprojection;
11866         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11867         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11868 }
11869 #else
11870 // broken
11871 {
11872         float projectionvector[4][3];
11873         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11874         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11875         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11876         projectionvector[0][0] = planes[0][0] * ilocalsize;
11877         projectionvector[0][1] = planes[1][0] * ilocalsize;
11878         projectionvector[0][2] = planes[2][0] * ilocalsize;
11879         projectionvector[1][0] = planes[0][1] * ilocalsize;
11880         projectionvector[1][1] = planes[1][1] * ilocalsize;
11881         projectionvector[1][2] = planes[2][1] * ilocalsize;
11882         projectionvector[2][0] = planes[0][2] * ilocalsize;
11883         projectionvector[2][1] = planes[1][2] * ilocalsize;
11884         projectionvector[2][2] = planes[2][2] * ilocalsize;
11885         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11886         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11887         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11888         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11889 }
11890 #endif
11891
11892         dynamic = model->surfmesh.isanimated;
11893         numsurfacelist = model->nummodelsurfaces;
11894         surfacelist = model->sortedmodelsurfaces;
11895         surfaces = model->data_surfaces;
11896
11897         bih = NULL;
11898         bih_triangles_count = -1;
11899         if(!dynamic)
11900         {
11901                 if(model->render_bih.numleafs)
11902                         bih = &model->render_bih;
11903                 else if(model->collision_bih.numleafs)
11904                         bih = &model->collision_bih;
11905         }
11906         if(bih)
11907                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11908         if(bih_triangles_count == 0)
11909                 return;
11910         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11911                 return;
11912         if(bih_triangles_count > 0)
11913         {
11914                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11915                 {
11916                         surfaceindex = bih_surfaces[triangleindex];
11917                         surface = surfaces + surfaceindex;
11918                         texture = surface->texture;
11919                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11920                                 continue;
11921                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11922                                 continue;
11923                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11924                 }
11925         }
11926         else
11927         {
11928                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11929                 {
11930                         surfaceindex = surfacelist[surfacelistindex];
11931                         surface = surfaces + surfaceindex;
11932                         // check cull box first because it rejects more than any other check
11933                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11934                                 continue;
11935                         // skip transparent surfaces
11936                         texture = surface->texture;
11937                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11938                                 continue;
11939                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11940                                 continue;
11941                         numtriangles = surface->num_triangles;
11942                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11943                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11944                 }
11945         }
11946 }
11947
11948 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11949 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)
11950 {
11951         int renderentityindex;
11952         float worldmins[3];
11953         float worldmaxs[3];
11954         entity_render_t *ent;
11955
11956         if (!cl_decals_newsystem.integer)
11957                 return;
11958
11959         worldmins[0] = worldorigin[0] - worldsize;
11960         worldmins[1] = worldorigin[1] - worldsize;
11961         worldmins[2] = worldorigin[2] - worldsize;
11962         worldmaxs[0] = worldorigin[0] + worldsize;
11963         worldmaxs[1] = worldorigin[1] + worldsize;
11964         worldmaxs[2] = worldorigin[2] + worldsize;
11965
11966         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11967
11968         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11969         {
11970                 ent = r_refdef.scene.entities[renderentityindex];
11971                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11972                         continue;
11973
11974                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11975         }
11976 }
11977
11978 typedef struct r_decalsystem_splatqueue_s
11979 {
11980         vec3_t worldorigin;
11981         vec3_t worldnormal;
11982         float color[4];
11983         float tcrange[4];
11984         float worldsize;
11985         int decalsequence;
11986 }
11987 r_decalsystem_splatqueue_t;
11988
11989 int r_decalsystem_numqueued = 0;
11990 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11991
11992 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)
11993 {
11994         r_decalsystem_splatqueue_t *queue;
11995
11996         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11997                 return;
11998
11999         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12000         VectorCopy(worldorigin, queue->worldorigin);
12001         VectorCopy(worldnormal, queue->worldnormal);
12002         Vector4Set(queue->color, r, g, b, a);
12003         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12004         queue->worldsize = worldsize;
12005         queue->decalsequence = cl.decalsequence++;
12006 }
12007
12008 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12009 {
12010         int i;
12011         r_decalsystem_splatqueue_t *queue;
12012
12013         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12014                 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);
12015         r_decalsystem_numqueued = 0;
12016 }
12017
12018 extern cvar_t cl_decals_max;
12019 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12020 {
12021         int i;
12022         decalsystem_t *decalsystem = &ent->decalsystem;
12023         int numdecals;
12024         int killsequence;
12025         tridecal_t *decal;
12026         float frametime;
12027         float lifetime;
12028
12029         if (!decalsystem->numdecals)
12030                 return;
12031
12032         if (r_showsurfaces.integer)
12033                 return;
12034
12035         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12036         {
12037                 R_DecalSystem_Reset(decalsystem);
12038                 return;
12039         }
12040
12041         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12042         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12043
12044         if (decalsystem->lastupdatetime)
12045                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12046         else
12047                 frametime = 0;
12048         decalsystem->lastupdatetime = r_refdef.scene.time;
12049         numdecals = decalsystem->numdecals;
12050
12051         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12052         {
12053                 if (decal->color4f[0][3])
12054                 {
12055                         decal->lived += frametime;
12056                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12057                         {
12058                                 memset(decal, 0, sizeof(*decal));
12059                                 if (decalsystem->freedecal > i)
12060                                         decalsystem->freedecal = i;
12061                         }
12062                 }
12063         }
12064         decal = decalsystem->decals;
12065         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12066                 numdecals--;
12067
12068         // collapse the array by shuffling the tail decals into the gaps
12069         for (;;)
12070         {
12071                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12072                         decalsystem->freedecal++;
12073                 if (decalsystem->freedecal == numdecals)
12074                         break;
12075                 decal[decalsystem->freedecal] = decal[--numdecals];
12076         }
12077
12078         decalsystem->numdecals = numdecals;
12079
12080         if (numdecals <= 0)
12081         {
12082                 // if there are no decals left, reset decalsystem
12083                 R_DecalSystem_Reset(decalsystem);
12084         }
12085 }
12086
12087 extern skinframe_t *decalskinframe;
12088 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12089 {
12090         int i;
12091         decalsystem_t *decalsystem = &ent->decalsystem;
12092         int numdecals;
12093         tridecal_t *decal;
12094         float faderate;
12095         float alpha;
12096         float *v3f;
12097         float *c4f;
12098         float *t2f;
12099         const int *e;
12100         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12101         int numtris = 0;
12102
12103         numdecals = decalsystem->numdecals;
12104         if (!numdecals)
12105                 return;
12106
12107         if (r_showsurfaces.integer)
12108                 return;
12109
12110         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12111         {
12112                 R_DecalSystem_Reset(decalsystem);
12113                 return;
12114         }
12115
12116         // if the model is static it doesn't matter what value we give for
12117         // wantnormals and wanttangents, so this logic uses only rules applicable
12118         // to a model, knowing that they are meaningless otherwise
12119         if (ent == r_refdef.scene.worldentity)
12120                 RSurf_ActiveWorldEntity();
12121         else
12122                 RSurf_ActiveModelEntity(ent, false, false, false);
12123
12124         decalsystem->lastupdatetime = r_refdef.scene.time;
12125
12126         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12127
12128         // update vertex positions for animated models
12129         v3f = decalsystem->vertex3f;
12130         c4f = decalsystem->color4f;
12131         t2f = decalsystem->texcoord2f;
12132         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12133         {
12134                 if (!decal->color4f[0][3])
12135                         continue;
12136
12137                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12138                         continue;
12139
12140                 // skip backfaces
12141                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12142                         continue;
12143
12144                 // update color values for fading decals
12145                 if (decal->lived >= cl_decals_time.value)
12146                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12147                 else
12148                         alpha = 1.0f;
12149
12150                 c4f[ 0] = decal->color4f[0][0] * alpha;
12151                 c4f[ 1] = decal->color4f[0][1] * alpha;
12152                 c4f[ 2] = decal->color4f[0][2] * alpha;
12153                 c4f[ 3] = 1;
12154                 c4f[ 4] = decal->color4f[1][0] * alpha;
12155                 c4f[ 5] = decal->color4f[1][1] * alpha;
12156                 c4f[ 6] = decal->color4f[1][2] * alpha;
12157                 c4f[ 7] = 1;
12158                 c4f[ 8] = decal->color4f[2][0] * alpha;
12159                 c4f[ 9] = decal->color4f[2][1] * alpha;
12160                 c4f[10] = decal->color4f[2][2] * alpha;
12161                 c4f[11] = 1;
12162
12163                 t2f[0] = decal->texcoord2f[0][0];
12164                 t2f[1] = decal->texcoord2f[0][1];
12165                 t2f[2] = decal->texcoord2f[1][0];
12166                 t2f[3] = decal->texcoord2f[1][1];
12167                 t2f[4] = decal->texcoord2f[2][0];
12168                 t2f[5] = decal->texcoord2f[2][1];
12169
12170                 // update vertex positions for animated models
12171                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12172                 {
12173                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12174                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12175                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12176                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12177                 }
12178                 else
12179                 {
12180                         VectorCopy(decal->vertex3f[0], v3f);
12181                         VectorCopy(decal->vertex3f[1], v3f + 3);
12182                         VectorCopy(decal->vertex3f[2], v3f + 6);
12183                 }
12184
12185                 if (r_refdef.fogenabled)
12186                 {
12187                         alpha = RSurf_FogVertex(v3f);
12188                         VectorScale(c4f, alpha, c4f);
12189                         alpha = RSurf_FogVertex(v3f + 3);
12190                         VectorScale(c4f + 4, alpha, c4f + 4);
12191                         alpha = RSurf_FogVertex(v3f + 6);
12192                         VectorScale(c4f + 8, alpha, c4f + 8);
12193                 }
12194
12195                 v3f += 9;
12196                 c4f += 12;
12197                 t2f += 6;
12198                 numtris++;
12199         }
12200
12201         if (numtris > 0)
12202         {
12203                 r_refdef.stats[r_stat_drawndecals] += numtris;
12204
12205                 // now render the decals all at once
12206                 // (this assumes they all use one particle font texture!)
12207                 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);
12208 //              R_Mesh_ResetTextureState();
12209                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12210                 GL_DepthMask(false);
12211                 GL_DepthRange(0, 1);
12212                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12213                 GL_DepthTest(true);
12214                 GL_CullFace(GL_NONE);
12215                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12216                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12217                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12218         }
12219 }
12220
12221 static void R_DrawModelDecals(void)
12222 {
12223         int i, numdecals;
12224
12225         // fade faster when there are too many decals
12226         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12227         for (i = 0;i < r_refdef.scene.numentities;i++)
12228                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12229
12230         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12231         for (i = 0;i < r_refdef.scene.numentities;i++)
12232                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12233                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12234
12235         R_DecalSystem_ApplySplatEntitiesQueue();
12236
12237         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12238         for (i = 0;i < r_refdef.scene.numentities;i++)
12239                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12240
12241         r_refdef.stats[r_stat_totaldecals] += numdecals;
12242
12243         if (r_showsurfaces.integer)
12244                 return;
12245
12246         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12247
12248         for (i = 0;i < r_refdef.scene.numentities;i++)
12249         {
12250                 if (!r_refdef.viewcache.entityvisible[i])
12251                         continue;
12252                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12253                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12254         }
12255 }
12256
12257 extern cvar_t mod_collision_bih;
12258 static void R_DrawDebugModel(void)
12259 {
12260         entity_render_t *ent = rsurface.entity;
12261         int i, j, flagsmask;
12262         const msurface_t *surface;
12263         dp_model_t *model = ent->model;
12264
12265         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12266                 return;
12267
12268         if (r_showoverdraw.value > 0)
12269         {
12270                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12271                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12272                 R_SetupShader_Generic_NoTexture(false, false);
12273                 GL_DepthTest(false);
12274                 GL_DepthMask(false);
12275                 GL_DepthRange(0, 1);
12276                 GL_BlendFunc(GL_ONE, GL_ONE);
12277                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12278                 {
12279                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12280                                 continue;
12281                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12282                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12283                         {
12284                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12285                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12286                                 if (!rsurface.texture->currentlayers->depthmask)
12287                                         GL_Color(c, 0, 0, 1.0f);
12288                                 else if (ent == r_refdef.scene.worldentity)
12289                                         GL_Color(c, c, c, 1.0f);
12290                                 else
12291                                         GL_Color(0, c, 0, 1.0f);
12292                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12293                                 RSurf_DrawBatch();
12294                         }
12295                 }
12296                 rsurface.texture = NULL;
12297         }
12298
12299         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12300
12301 //      R_Mesh_ResetTextureState();
12302         R_SetupShader_Generic_NoTexture(false, false);
12303         GL_DepthRange(0, 1);
12304         GL_DepthTest(!r_showdisabledepthtest.integer);
12305         GL_DepthMask(false);
12306         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12307
12308         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12309         {
12310                 int triangleindex;
12311                 int bihleafindex;
12312                 qboolean cullbox = false;
12313                 const q3mbrush_t *brush;
12314                 const bih_t *bih = &model->collision_bih;
12315                 const bih_leaf_t *bihleaf;
12316                 float vertex3f[3][3];
12317                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12318                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12319                 {
12320                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12321                                 continue;
12322                         switch (bihleaf->type)
12323                         {
12324                         case BIH_BRUSH:
12325                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12326                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12327                                 {
12328                                         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);
12329                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12330                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12331                                 }
12332                                 break;
12333                         case BIH_COLLISIONTRIANGLE:
12334                                 triangleindex = bihleaf->itemindex;
12335                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12336                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12337                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12338                                 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);
12339                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12340                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12341                                 break;
12342                         case BIH_RENDERTRIANGLE:
12343                                 triangleindex = bihleaf->itemindex;
12344                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12345                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12346                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12347                                 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);
12348                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12349                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12350                                 break;
12351                         }
12352                 }
12353         }
12354
12355         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12356
12357 #ifndef USE_GLES2
12358         if (r_showtris.integer && qglPolygonMode)
12359         {
12360                 if (r_showdisabledepthtest.integer)
12361                 {
12362                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12363                         GL_DepthMask(false);
12364                 }
12365                 else
12366                 {
12367                         GL_BlendFunc(GL_ONE, GL_ZERO);
12368                         GL_DepthMask(true);
12369                 }
12370                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12371                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12372                 {
12373                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12374                                 continue;
12375                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12376                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12377                         {
12378                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12379                                 if (!rsurface.texture->currentlayers->depthmask)
12380                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12381                                 else if (ent == r_refdef.scene.worldentity)
12382                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12383                                 else
12384                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12385                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12386                                 RSurf_DrawBatch();
12387                         }
12388                 }
12389                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12390                 rsurface.texture = NULL;
12391         }
12392
12393         if (r_shownormals.value != 0 && qglBegin)
12394         {
12395                 int l, k;
12396                 vec3_t v;
12397                 if (r_showdisabledepthtest.integer)
12398                 {
12399                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12400                         GL_DepthMask(false);
12401                 }
12402                 else
12403                 {
12404                         GL_BlendFunc(GL_ONE, GL_ZERO);
12405                         GL_DepthMask(true);
12406                 }
12407                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12408                 {
12409                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12410                                 continue;
12411                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12412                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12413                         {
12414                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12415                                 qglBegin(GL_LINES);
12416                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12417                                 {
12418                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12419                                         {
12420                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12421                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12422                                                 qglVertex3f(v[0], v[1], v[2]);
12423                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12424                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12425                                                 qglVertex3f(v[0], v[1], v[2]);
12426                                         }
12427                                 }
12428                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12429                                 {
12430                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12431                                         {
12432                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12433                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12434                                                 qglVertex3f(v[0], v[1], v[2]);
12435                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12436                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12437                                                 qglVertex3f(v[0], v[1], v[2]);
12438                                         }
12439                                 }
12440                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12441                                 {
12442                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12443                                         {
12444                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12445                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12446                                                 qglVertex3f(v[0], v[1], v[2]);
12447                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12448                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12449                                                 qglVertex3f(v[0], v[1], v[2]);
12450                                         }
12451                                 }
12452                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12453                                 {
12454                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12455                                         {
12456                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12457                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12458                                                 qglVertex3f(v[0], v[1], v[2]);
12459                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12460                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12461                                                 qglVertex3f(v[0], v[1], v[2]);
12462                                         }
12463                                 }
12464                                 qglEnd();
12465                                 CHECKGLERROR
12466                         }
12467                 }
12468                 rsurface.texture = NULL;
12469         }
12470 #endif
12471 }
12472
12473 int r_maxsurfacelist = 0;
12474 const msurface_t **r_surfacelist = NULL;
12475 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12476 {
12477         int i, j, endj, flagsmask;
12478         dp_model_t *model = r_refdef.scene.worldmodel;
12479         msurface_t *surfaces;
12480         unsigned char *update;
12481         int numsurfacelist = 0;
12482         if (model == NULL)
12483                 return;
12484
12485         if (r_maxsurfacelist < model->num_surfaces)
12486         {
12487                 r_maxsurfacelist = model->num_surfaces;
12488                 if (r_surfacelist)
12489                         Mem_Free((msurface_t**)r_surfacelist);
12490                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12491         }
12492
12493         RSurf_ActiveWorldEntity();
12494
12495         surfaces = model->data_surfaces;
12496         update = model->brushq1.lightmapupdateflags;
12497
12498         // update light styles on this submodel
12499         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12500         {
12501                 model_brush_lightstyleinfo_t *style;
12502                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12503                 {
12504                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12505                         {
12506                                 int *list = style->surfacelist;
12507                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12508                                 for (j = 0;j < style->numsurfaces;j++)
12509                                         update[list[j]] = true;
12510                         }
12511                 }
12512         }
12513
12514         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12515
12516         if (debug)
12517         {
12518                 R_DrawDebugModel();
12519                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12520                 return;
12521         }
12522
12523         rsurface.lightmaptexture = NULL;
12524         rsurface.deluxemaptexture = NULL;
12525         rsurface.uselightmaptexture = false;
12526         rsurface.texture = NULL;
12527         rsurface.rtlight = NULL;
12528         numsurfacelist = 0;
12529         // add visible surfaces to draw list
12530         for (i = 0;i < model->nummodelsurfaces;i++)
12531         {
12532                 j = model->sortedmodelsurfaces[i];
12533                 if (r_refdef.viewcache.world_surfacevisible[j])
12534                         r_surfacelist[numsurfacelist++] = surfaces + j;
12535         }
12536         // update lightmaps if needed
12537         if (model->brushq1.firstrender)
12538         {
12539                 model->brushq1.firstrender = false;
12540                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12541                         if (update[j])
12542                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12543         }
12544         else if (update)
12545         {
12546                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12547                         if (r_refdef.viewcache.world_surfacevisible[j])
12548                                 if (update[j])
12549                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12550         }
12551         // don't do anything if there were no surfaces
12552         if (!numsurfacelist)
12553         {
12554                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12555                 return;
12556         }
12557         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12558
12559         // add to stats if desired
12560         if (r_speeds.integer && !skysurfaces && !depthonly)
12561         {
12562                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12563                 for (j = 0;j < numsurfacelist;j++)
12564                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12565         }
12566
12567         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12568 }
12569
12570 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12571 {
12572         int i, j, endj, flagsmask;
12573         dp_model_t *model = ent->model;
12574         msurface_t *surfaces;
12575         unsigned char *update;
12576         int numsurfacelist = 0;
12577         if (model == NULL)
12578                 return;
12579
12580         if (r_maxsurfacelist < model->num_surfaces)
12581         {
12582                 r_maxsurfacelist = model->num_surfaces;
12583                 if (r_surfacelist)
12584                         Mem_Free((msurface_t **)r_surfacelist);
12585                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12586         }
12587
12588         // if the model is static it doesn't matter what value we give for
12589         // wantnormals and wanttangents, so this logic uses only rules applicable
12590         // to a model, knowing that they are meaningless otherwise
12591         if (ent == r_refdef.scene.worldentity)
12592                 RSurf_ActiveWorldEntity();
12593         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12594                 RSurf_ActiveModelEntity(ent, false, false, false);
12595         else if (prepass)
12596                 RSurf_ActiveModelEntity(ent, true, true, true);
12597         else if (depthonly)
12598         {
12599                 switch (vid.renderpath)
12600                 {
12601                 case RENDERPATH_GL20:
12602                 case RENDERPATH_D3D9:
12603                 case RENDERPATH_D3D10:
12604                 case RENDERPATH_D3D11:
12605                 case RENDERPATH_SOFT:
12606                 case RENDERPATH_GLES2:
12607                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12608                         break;
12609                 case RENDERPATH_GL11:
12610                 case RENDERPATH_GL13:
12611                 case RENDERPATH_GLES1:
12612                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12613                         break;
12614                 }
12615         }
12616         else
12617         {
12618                 switch (vid.renderpath)
12619                 {
12620                 case RENDERPATH_GL20:
12621                 case RENDERPATH_D3D9:
12622                 case RENDERPATH_D3D10:
12623                 case RENDERPATH_D3D11:
12624                 case RENDERPATH_SOFT:
12625                 case RENDERPATH_GLES2:
12626                         RSurf_ActiveModelEntity(ent, true, true, false);
12627                         break;
12628                 case RENDERPATH_GL11:
12629                 case RENDERPATH_GL13:
12630                 case RENDERPATH_GLES1:
12631                         RSurf_ActiveModelEntity(ent, true, false, false);
12632                         break;
12633                 }
12634         }
12635
12636         surfaces = model->data_surfaces;
12637         update = model->brushq1.lightmapupdateflags;
12638
12639         // update light styles
12640         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12641         {
12642                 model_brush_lightstyleinfo_t *style;
12643                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12644                 {
12645                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12646                         {
12647                                 int *list = style->surfacelist;
12648                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12649                                 for (j = 0;j < style->numsurfaces;j++)
12650                                         update[list[j]] = true;
12651                         }
12652                 }
12653         }
12654
12655         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12656
12657         if (debug)
12658         {
12659                 R_DrawDebugModel();
12660                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12661                 return;
12662         }
12663
12664         rsurface.lightmaptexture = NULL;
12665         rsurface.deluxemaptexture = NULL;
12666         rsurface.uselightmaptexture = false;
12667         rsurface.texture = NULL;
12668         rsurface.rtlight = NULL;
12669         numsurfacelist = 0;
12670         // add visible surfaces to draw list
12671         for (i = 0;i < model->nummodelsurfaces;i++)
12672                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12673         // don't do anything if there were no surfaces
12674         if (!numsurfacelist)
12675         {
12676                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12677                 return;
12678         }
12679         // update lightmaps if needed
12680         if (update)
12681         {
12682                 int updated = 0;
12683                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12684                 {
12685                         if (update[j])
12686                         {
12687                                 updated++;
12688                                 R_BuildLightMap(ent, surfaces + j);
12689                         }
12690                 }
12691         }
12692
12693         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12694
12695         // add to stats if desired
12696         if (r_speeds.integer && !skysurfaces && !depthonly)
12697         {
12698                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12699                 for (j = 0;j < numsurfacelist;j++)
12700                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12701         }
12702
12703         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12704 }
12705
12706 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12707 {
12708         static texture_t texture;
12709         static msurface_t surface;
12710         const msurface_t *surfacelist = &surface;
12711
12712         // fake enough texture and surface state to render this geometry
12713
12714         texture.update_lastrenderframe = -1; // regenerate this texture
12715         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12716         texture.currentskinframe = skinframe;
12717         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12718         texture.offsetmapping = OFFSETMAPPING_OFF;
12719         texture.offsetscale = 1;
12720         texture.specularscalemod = 1;
12721         texture.specularpowermod = 1;
12722         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12723         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12724         // JUST GREP FOR "specularscalemod = 1".
12725
12726         surface.texture = &texture;
12727         surface.num_triangles = numtriangles;
12728         surface.num_firsttriangle = firsttriangle;
12729         surface.num_vertices = numvertices;
12730         surface.num_firstvertex = firstvertex;
12731
12732         // now render it
12733         rsurface.texture = R_GetCurrentTexture(surface.texture);
12734         rsurface.lightmaptexture = NULL;
12735         rsurface.deluxemaptexture = NULL;
12736         rsurface.uselightmaptexture = false;
12737         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12738 }
12739
12740 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)
12741 {
12742         static msurface_t surface;
12743         const msurface_t *surfacelist = &surface;
12744
12745         // fake enough texture and surface state to render this geometry
12746         surface.texture = texture;
12747         surface.num_triangles = numtriangles;
12748         surface.num_firsttriangle = firsttriangle;
12749         surface.num_vertices = numvertices;
12750         surface.num_firstvertex = firstvertex;
12751
12752         // now render it
12753         rsurface.texture = R_GetCurrentTexture(surface.texture);
12754         rsurface.lightmaptexture = NULL;
12755         rsurface.deluxemaptexture = NULL;
12756         rsurface.uselightmaptexture = false;
12757         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12758 }