]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
some cleanup of glDelete calls to guard against bugs caused by GL
[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                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1167                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1168                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1169                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1170                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1171                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1172                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1173                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1174                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1175                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1176                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1177                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1178                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1179                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1180                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1181                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1182                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1183                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1184                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1185                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1186                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1187                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1188                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1189                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1190                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1191                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1192                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1193                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1194                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1195                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1196                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1197                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1198                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1199                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1200                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1201                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1202                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1203                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1204                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1205                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1206                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1207                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1208                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1209                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1210                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1211                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1212                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1213                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1214                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1215                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1216                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1217                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1218                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1219                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1220                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1221                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1222                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1223                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1224                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1225                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1226                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1227                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1228                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1229                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1230                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1231                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1232                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1233                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1234                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1235                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1236                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1237                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1238                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1239                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1240                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1241                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1242                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1243                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1244                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1245                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1246                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1247                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1248                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1249                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1250                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1251                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1252                 // initialize the samplers to refer to the texture units we use
1253                 p->tex_Texture_First = -1;
1254                 p->tex_Texture_Second = -1;
1255                 p->tex_Texture_GammaRamps = -1;
1256                 p->tex_Texture_Normal = -1;
1257                 p->tex_Texture_Color = -1;
1258                 p->tex_Texture_Gloss = -1;
1259                 p->tex_Texture_Glow = -1;
1260                 p->tex_Texture_SecondaryNormal = -1;
1261                 p->tex_Texture_SecondaryColor = -1;
1262                 p->tex_Texture_SecondaryGloss = -1;
1263                 p->tex_Texture_SecondaryGlow = -1;
1264                 p->tex_Texture_Pants = -1;
1265                 p->tex_Texture_Shirt = -1;
1266                 p->tex_Texture_FogHeightTexture = -1;
1267                 p->tex_Texture_FogMask = -1;
1268                 p->tex_Texture_Lightmap = -1;
1269                 p->tex_Texture_Deluxemap = -1;
1270                 p->tex_Texture_Attenuation = -1;
1271                 p->tex_Texture_Cube = -1;
1272                 p->tex_Texture_Refraction = -1;
1273                 p->tex_Texture_Reflection = -1;
1274                 p->tex_Texture_ShadowMap2D = -1;
1275                 p->tex_Texture_CubeProjection = -1;
1276                 p->tex_Texture_ScreenNormalMap = -1;
1277                 p->tex_Texture_ScreenDiffuse = -1;
1278                 p->tex_Texture_ScreenSpecular = -1;
1279                 p->tex_Texture_ReflectMask = -1;
1280                 p->tex_Texture_ReflectCube = -1;
1281                 p->tex_Texture_BounceGrid = -1;
1282                 // bind the texture samplers in use
1283                 sampler = 0;
1284                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1285                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1286                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1287                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1288                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1289                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1290                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1291                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1292                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1293                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1294                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1295                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1296                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1297                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1298                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1299                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1300                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1301                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1302                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1303                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1304                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1305                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1306                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1307                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1308                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1309                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1310                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1311                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1312                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1313                 // get the uniform block indices so we can bind them
1314                 if (vid.support.arb_uniform_buffer_object)
1315                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1316                 else
1317                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1318                 // clear the uniform block bindings
1319                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1320                 // bind the uniform blocks in use
1321                 ubibind = 0;
1322                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1323                 // we're done compiling and setting up the shader, at least until it is used
1324                 CHECKGLERROR
1325                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1326         }
1327         else
1328                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1329
1330         // free the strings
1331         if (sourcestring)
1332                 Mem_Free(sourcestring);
1333 }
1334
1335 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1336 {
1337         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1338         if (r_glsl_permutation != perm)
1339         {
1340                 r_glsl_permutation = perm;
1341                 if (!r_glsl_permutation->program)
1342                 {
1343                         if (!r_glsl_permutation->compiled)
1344                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1345                         if (!r_glsl_permutation->program)
1346                         {
1347                                 // remove features until we find a valid permutation
1348                                 int i;
1349                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1350                                 {
1351                                         // reduce i more quickly whenever it would not remove any bits
1352                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1353                                         if (!(permutation & j))
1354                                                 continue;
1355                                         permutation -= j;
1356                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1357                                         if (!r_glsl_permutation->compiled)
1358                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1359                                         if (r_glsl_permutation->program)
1360                                                 break;
1361                                 }
1362                                 if (i >= SHADERPERMUTATION_COUNT)
1363                                 {
1364                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1365                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1366                                         qglUseProgram(0);CHECKGLERROR
1367                                         return; // no bit left to clear, entire mode is broken
1368                                 }
1369                         }
1370                 }
1371                 CHECKGLERROR
1372                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1373         }
1374         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1375         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1376         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1377 }
1378
1379 #ifdef SUPPORTD3D
1380
1381 #ifdef SUPPORTD3D
1382 #include <d3d9.h>
1383 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1384 extern D3DCAPS9 vid_d3d9caps;
1385 #endif
1386
1387 struct r_hlsl_permutation_s;
1388 typedef struct r_hlsl_permutation_s
1389 {
1390         /// hash lookup data
1391         struct r_hlsl_permutation_s *hashnext;
1392         unsigned int mode;
1393         unsigned int permutation;
1394
1395         /// indicates if we have tried compiling this permutation already
1396         qboolean compiled;
1397         /// NULL if compilation failed
1398         IDirect3DVertexShader9 *vertexshader;
1399         IDirect3DPixelShader9 *pixelshader;
1400 }
1401 r_hlsl_permutation_t;
1402
1403 typedef enum D3DVSREGISTER_e
1404 {
1405         D3DVSREGISTER_TexMatrix = 0, // float4x4
1406         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1407         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1408         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1409         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1410         D3DVSREGISTER_ModelToLight = 20, // float4x4
1411         D3DVSREGISTER_EyePosition = 24,
1412         D3DVSREGISTER_FogPlane = 25,
1413         D3DVSREGISTER_LightDir = 26,
1414         D3DVSREGISTER_LightPosition = 27,
1415 }
1416 D3DVSREGISTER_t;
1417
1418 typedef enum D3DPSREGISTER_e
1419 {
1420         D3DPSREGISTER_Alpha = 0,
1421         D3DPSREGISTER_BloomBlur_Parameters = 1,
1422         D3DPSREGISTER_ClientTime = 2,
1423         D3DPSREGISTER_Color_Ambient = 3,
1424         D3DPSREGISTER_Color_Diffuse = 4,
1425         D3DPSREGISTER_Color_Specular = 5,
1426         D3DPSREGISTER_Color_Glow = 6,
1427         D3DPSREGISTER_Color_Pants = 7,
1428         D3DPSREGISTER_Color_Shirt = 8,
1429         D3DPSREGISTER_DeferredColor_Ambient = 9,
1430         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1431         D3DPSREGISTER_DeferredColor_Specular = 11,
1432         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1433         D3DPSREGISTER_DeferredMod_Specular = 13,
1434         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1435         D3DPSREGISTER_EyePosition = 15, // unused
1436         D3DPSREGISTER_FogColor = 16,
1437         D3DPSREGISTER_FogHeightFade = 17,
1438         D3DPSREGISTER_FogPlane = 18,
1439         D3DPSREGISTER_FogPlaneViewDist = 19,
1440         D3DPSREGISTER_FogRangeRecip = 20,
1441         D3DPSREGISTER_LightColor = 21,
1442         D3DPSREGISTER_LightDir = 22, // unused
1443         D3DPSREGISTER_LightPosition = 23,
1444         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1445         D3DPSREGISTER_PixelSize = 25,
1446         D3DPSREGISTER_ReflectColor = 26,
1447         D3DPSREGISTER_ReflectFactor = 27,
1448         D3DPSREGISTER_ReflectOffset = 28,
1449         D3DPSREGISTER_RefractColor = 29,
1450         D3DPSREGISTER_Saturation = 30,
1451         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1452         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1453         D3DPSREGISTER_ScreenToDepth = 33,
1454         D3DPSREGISTER_ShadowMap_Parameters = 34,
1455         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1456         D3DPSREGISTER_SpecularPower = 36,
1457         D3DPSREGISTER_UserVec1 = 37,
1458         D3DPSREGISTER_UserVec2 = 38,
1459         D3DPSREGISTER_UserVec3 = 39,
1460         D3DPSREGISTER_UserVec4 = 40,
1461         D3DPSREGISTER_ViewTintColor = 41,
1462         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1463         D3DPSREGISTER_BloomColorSubtract = 43,
1464         D3DPSREGISTER_ViewToLight = 44, // float4x4
1465         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1466         D3DPSREGISTER_NormalmapScrollBlend = 52,
1467         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1468         D3DPSREGISTER_OffsetMapping_Bias = 54,
1469         // next at 54
1470 }
1471 D3DPSREGISTER_t;
1472
1473 /// information about each possible shader permutation
1474 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1475 /// currently selected permutation
1476 r_hlsl_permutation_t *r_hlsl_permutation;
1477 /// storage for permutations linked in the hash table
1478 memexpandablearray_t r_hlsl_permutationarray;
1479
1480 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1481 {
1482         //unsigned int hashdepth = 0;
1483         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1484         r_hlsl_permutation_t *p;
1485         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1486         {
1487                 if (p->mode == mode && p->permutation == permutation)
1488                 {
1489                         //if (hashdepth > 10)
1490                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1491                         return p;
1492                 }
1493                 //hashdepth++;
1494         }
1495         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1496         p->mode = mode;
1497         p->permutation = permutation;
1498         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1499         r_hlsl_permutationhash[mode][hashindex] = p;
1500         //if (hashdepth > 10)
1501         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1502         return p;
1503 }
1504
1505 #include <d3dx9.h>
1506 //#include <d3dx9shader.h>
1507 //#include <d3dx9mesh.h>
1508
1509 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1510 {
1511         DWORD *vsbin = NULL;
1512         DWORD *psbin = NULL;
1513         fs_offset_t vsbinsize;
1514         fs_offset_t psbinsize;
1515 //      IDirect3DVertexShader9 *vs = NULL;
1516 //      IDirect3DPixelShader9 *ps = NULL;
1517         ID3DXBuffer *vslog = NULL;
1518         ID3DXBuffer *vsbuffer = NULL;
1519         ID3DXConstantTable *vsconstanttable = NULL;
1520         ID3DXBuffer *pslog = NULL;
1521         ID3DXBuffer *psbuffer = NULL;
1522         ID3DXConstantTable *psconstanttable = NULL;
1523         int vsresult = 0;
1524         int psresult = 0;
1525         char temp[MAX_INPUTLINE];
1526         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1527         char vabuf[1024];
1528         qboolean debugshader = gl_paranoid.integer != 0;
1529         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1530         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1531         if (!debugshader)
1532         {
1533                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1534                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1535         }
1536         if ((!vsbin && vertstring) || (!psbin && fragstring))
1537         {
1538                 const char* dllnames_d3dx9 [] =
1539                 {
1540                         "d3dx9_43.dll",
1541                         "d3dx9_42.dll",
1542                         "d3dx9_41.dll",
1543                         "d3dx9_40.dll",
1544                         "d3dx9_39.dll",
1545                         "d3dx9_38.dll",
1546                         "d3dx9_37.dll",
1547                         "d3dx9_36.dll",
1548                         "d3dx9_35.dll",
1549                         "d3dx9_34.dll",
1550                         "d3dx9_33.dll",
1551                         "d3dx9_32.dll",
1552                         "d3dx9_31.dll",
1553                         "d3dx9_30.dll",
1554                         "d3dx9_29.dll",
1555                         "d3dx9_28.dll",
1556                         "d3dx9_27.dll",
1557                         "d3dx9_26.dll",
1558                         "d3dx9_25.dll",
1559                         "d3dx9_24.dll",
1560                         NULL
1561                 };
1562                 dllhandle_t d3dx9_dll = NULL;
1563                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1564                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1565                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1566                 dllfunction_t d3dx9_dllfuncs[] =
1567                 {
1568                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1569                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1570                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1571                         {NULL, NULL}
1572                 };
1573                 // 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...
1574 #ifndef ID3DXBuffer_GetBufferPointer
1575 #if !defined(__cplusplus) || defined(CINTERFACE)
1576 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1577 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1578 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1579 #else
1580 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1581 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1582 #define ID3DXBuffer_Release(p)            (p)->Release()
1583 #endif
1584 #endif
1585                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1586                 {
1587                         DWORD shaderflags = 0;
1588                         if (debugshader)
1589                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1590                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1591                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1592                         if (vertstring && vertstring[0])
1593                         {
1594                                 if (debugshader)
1595                                 {
1596                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1597                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1598                                 }
1599                                 else
1600                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1601                                 if (vsbuffer)
1602                                 {
1603                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1604                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1605                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1606                                         ID3DXBuffer_Release(vsbuffer);
1607                                 }
1608                                 if (vslog)
1609                                 {
1610                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1611                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1612                                         ID3DXBuffer_Release(vslog);
1613                                 }
1614                         }
1615                         if (fragstring && fragstring[0])
1616                         {
1617                                 if (debugshader)
1618                                 {
1619                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1620                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1621                                 }
1622                                 else
1623                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1624                                 if (psbuffer)
1625                                 {
1626                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1627                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1628                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1629                                         ID3DXBuffer_Release(psbuffer);
1630                                 }
1631                                 if (pslog)
1632                                 {
1633                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1634                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1635                                         ID3DXBuffer_Release(pslog);
1636                                 }
1637                         }
1638                         Sys_UnloadLibrary(&d3dx9_dll);
1639                 }
1640                 else
1641                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1642         }
1643         if (vsbin && psbin)
1644         {
1645                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1646                 if (FAILED(vsresult))
1647                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1648                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1649                 if (FAILED(psresult))
1650                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1651         }
1652         // free the shader data
1653         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1654         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1655 }
1656
1657 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1658 {
1659         int i;
1660         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1661         int vertstring_length = 0;
1662         int geomstring_length = 0;
1663         int fragstring_length = 0;
1664         char *t;
1665         char *sourcestring;
1666         char *vertstring, *geomstring, *fragstring;
1667         char permutationname[256];
1668         char cachename[256];
1669         int vertstrings_count = 0;
1670         int geomstrings_count = 0;
1671         int fragstrings_count = 0;
1672         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1673         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1674         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1675
1676         if (p->compiled)
1677                 return;
1678         p->compiled = true;
1679         p->vertexshader = NULL;
1680         p->pixelshader = NULL;
1681
1682         permutationname[0] = 0;
1683         cachename[0] = 0;
1684         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1685
1686         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1687         strlcat(cachename, "hlsl/", sizeof(cachename));
1688
1689         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1690         vertstrings_count = 0;
1691         geomstrings_count = 0;
1692         fragstrings_count = 0;
1693         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1694         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1695         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1696
1697         // the first pretext is which type of shader to compile as
1698         // (later these will all be bound together as a program object)
1699         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1700         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1701         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1702
1703         // the second pretext is the mode (for example a light source)
1704         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1705         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1706         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1707         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1708         strlcat(cachename, modeinfo->name, sizeof(cachename));
1709
1710         // now add all the permutation pretexts
1711         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1712         {
1713                 if (permutation & (1<<i))
1714                 {
1715                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1716                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1717                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1718                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1719                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1720                 }
1721                 else
1722                 {
1723                         // keep line numbers correct
1724                         vertstrings_list[vertstrings_count++] = "\n";
1725                         geomstrings_list[geomstrings_count++] = "\n";
1726                         fragstrings_list[fragstrings_count++] = "\n";
1727                 }
1728         }
1729
1730         // add static parms
1731         R_CompileShader_AddStaticParms(mode, permutation);
1732         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1733         vertstrings_count += shaderstaticparms_count;
1734         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1735         geomstrings_count += shaderstaticparms_count;
1736         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1737         fragstrings_count += shaderstaticparms_count;
1738
1739         // replace spaces in the cachename with _ characters
1740         for (i = 0;cachename[i];i++)
1741                 if (cachename[i] == ' ')
1742                         cachename[i] = '_';
1743
1744         // now append the shader text itself
1745         vertstrings_list[vertstrings_count++] = sourcestring;
1746         geomstrings_list[geomstrings_count++] = sourcestring;
1747         fragstrings_list[fragstrings_count++] = sourcestring;
1748
1749         vertstring_length = 0;
1750         for (i = 0;i < vertstrings_count;i++)
1751                 vertstring_length += strlen(vertstrings_list[i]);
1752         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1753         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1754                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1755
1756         geomstring_length = 0;
1757         for (i = 0;i < geomstrings_count;i++)
1758                 geomstring_length += strlen(geomstrings_list[i]);
1759         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1760         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1761                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1762
1763         fragstring_length = 0;
1764         for (i = 0;i < fragstrings_count;i++)
1765                 fragstring_length += strlen(fragstrings_list[i]);
1766         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1767         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1768                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1769
1770         // try to load the cached shader, or generate one
1771         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1772
1773         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1774                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1775         else
1776                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1777
1778         // free the strings
1779         if (vertstring)
1780                 Mem_Free(vertstring);
1781         if (geomstring)
1782                 Mem_Free(geomstring);
1783         if (fragstring)
1784                 Mem_Free(fragstring);
1785         if (sourcestring)
1786                 Mem_Free(sourcestring);
1787 }
1788
1789 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1790 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1791 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);}
1792 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);}
1793 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);}
1794 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);}
1795
1796 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1797 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1798 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);}
1799 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);}
1800 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);}
1801 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);}
1802
1803 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1804 {
1805         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1806         if (r_hlsl_permutation != perm)
1807         {
1808                 r_hlsl_permutation = perm;
1809                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1810                 {
1811                         if (!r_hlsl_permutation->compiled)
1812                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1813                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1814                         {
1815                                 // remove features until we find a valid permutation
1816                                 int i;
1817                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1818                                 {
1819                                         // reduce i more quickly whenever it would not remove any bits
1820                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1821                                         if (!(permutation & j))
1822                                                 continue;
1823                                         permutation -= j;
1824                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1825                                         if (!r_hlsl_permutation->compiled)
1826                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1827                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1828                                                 break;
1829                                 }
1830                                 if (i >= SHADERPERMUTATION_COUNT)
1831                                 {
1832                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1833                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1834                                         return; // no bit left to clear, entire mode is broken
1835                                 }
1836                         }
1837                 }
1838                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1839                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1840         }
1841         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1842         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1843         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1844 }
1845 #endif
1846
1847 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1848 {
1849         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1850         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1851         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1852         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1853 }
1854
1855 void R_GLSL_Restart_f(void)
1856 {
1857         unsigned int i, limit;
1858         if (glslshaderstring)
1859                 Mem_Free(glslshaderstring);
1860         glslshaderstring = NULL;
1861         if (hlslshaderstring)
1862                 Mem_Free(hlslshaderstring);
1863         hlslshaderstring = NULL;
1864         switch(vid.renderpath)
1865         {
1866         case RENDERPATH_D3D9:
1867 #ifdef SUPPORTD3D
1868                 {
1869                         r_hlsl_permutation_t *p;
1870                         r_hlsl_permutation = NULL;
1871                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1872                         for (i = 0;i < limit;i++)
1873                         {
1874                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1875                                 {
1876                                         if (p->vertexshader)
1877                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1878                                         if (p->pixelshader)
1879                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1880                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1881                                 }
1882                         }
1883                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1884                 }
1885 #endif
1886                 break;
1887         case RENDERPATH_D3D10:
1888                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1889                 break;
1890         case RENDERPATH_D3D11:
1891                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1892                 break;
1893         case RENDERPATH_GL20:
1894         case RENDERPATH_GLES2:
1895                 {
1896                         r_glsl_permutation_t *p;
1897                         r_glsl_permutation = NULL;
1898                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1899                         for (i = 0;i < limit;i++)
1900                         {
1901                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1902                                 {
1903                                         GL_Backend_FreeProgram(p->program);
1904                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1905                                 }
1906                         }
1907                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1908                 }
1909                 break;
1910         case RENDERPATH_GL11:
1911         case RENDERPATH_GL13:
1912         case RENDERPATH_GLES1:
1913                 break;
1914         case RENDERPATH_SOFT:
1915                 break;
1916         }
1917 }
1918
1919 static void R_GLSL_DumpShader_f(void)
1920 {
1921         int i, language, mode, dupe;
1922         char *text;
1923         shadermodeinfo_t *modeinfo;
1924         qfile_t *file;
1925
1926         for (language = 0;language < 2;language++)
1927         {
1928                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1929                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1930                 {
1931                         // don't dump the same file multiple times (most or all shaders come from the same file)
1932                         for (dupe = mode - 1;dupe >= 0;dupe--)
1933                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1934                                         break;
1935                         if (dupe >= 0)
1936                                 continue;
1937                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1938                         if (!text)
1939                                 continue;
1940                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1941                         if (file)
1942                         {
1943                                 FS_Print(file, "/* The engine may define the following macros:\n");
1944                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1945                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1946                                         FS_Print(file, modeinfo[i].pretext);
1947                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1948                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1949                                 FS_Print(file, "*/\n");
1950                                 FS_Print(file, text);
1951                                 FS_Close(file);
1952                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1953                         }
1954                         else
1955                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1956                         Mem_Free(text);
1957                 }
1958         }
1959 }
1960
1961 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1962 {
1963         unsigned int permutation = 0;
1964         if (r_trippy.integer && !notrippy)
1965                 permutation |= SHADERPERMUTATION_TRIPPY;
1966         permutation |= SHADERPERMUTATION_VIEWTINT;
1967         if (first)
1968                 permutation |= SHADERPERMUTATION_DIFFUSE;
1969         if (second)
1970                 permutation |= SHADERPERMUTATION_SPECULAR;
1971         if (texturemode == GL_MODULATE)
1972                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1973         else if (texturemode == GL_ADD)
1974                 permutation |= SHADERPERMUTATION_GLOW;
1975         else if (texturemode == GL_DECAL)
1976                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1977         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1978                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1979         if (suppresstexalpha)
1980                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1981         if (!second)
1982                 texturemode = GL_MODULATE;
1983         if (vid.allowalphatocoverage)
1984                 GL_AlphaToCoverage(false);
1985         switch (vid.renderpath)
1986         {
1987         case RENDERPATH_D3D9:
1988 #ifdef SUPPORTD3D
1989                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1990                 R_Mesh_TexBind(GL20TU_FIRST , first );
1991                 R_Mesh_TexBind(GL20TU_SECOND, second);
1992                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1993                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1994 #endif
1995                 break;
1996         case RENDERPATH_D3D10:
1997                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1998                 break;
1999         case RENDERPATH_D3D11:
2000                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2001                 break;
2002         case RENDERPATH_GL20:
2003         case RENDERPATH_GLES2:
2004                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2005                 if (r_glsl_permutation->tex_Texture_First >= 0)
2006                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2007                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2008                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2009                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2010                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2011                 break;
2012         case RENDERPATH_GL13:
2013         case RENDERPATH_GLES1:
2014                 R_Mesh_TexBind(0, first );
2015                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2016                 R_Mesh_TexMatrix(0, NULL);
2017                 R_Mesh_TexBind(1, second);
2018                 if (second)
2019                 {
2020                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2021                         R_Mesh_TexMatrix(1, NULL);
2022                 }
2023                 break;
2024         case RENDERPATH_GL11:
2025                 R_Mesh_TexBind(0, first );
2026                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2027                 R_Mesh_TexMatrix(0, NULL);
2028                 break;
2029         case RENDERPATH_SOFT:
2030                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2031                 R_Mesh_TexBind(GL20TU_FIRST , first );
2032                 R_Mesh_TexBind(GL20TU_SECOND, second);
2033                 break;
2034         }
2035 }
2036
2037 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2038 {
2039         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2040 }
2041
2042 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2043 {
2044         unsigned int permutation = 0;
2045         if (r_trippy.integer && !notrippy)
2046                 permutation |= SHADERPERMUTATION_TRIPPY;
2047         if (depthrgb)
2048                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2049         if (skeletal)
2050                 permutation |= SHADERPERMUTATION_SKELETAL;
2051
2052         if (vid.allowalphatocoverage)
2053                 GL_AlphaToCoverage(false);
2054         switch (vid.renderpath)
2055         {
2056         case RENDERPATH_D3D9:
2057 #ifdef SUPPORTD3D
2058                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2059 #endif
2060                 break;
2061         case RENDERPATH_D3D10:
2062                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2063                 break;
2064         case RENDERPATH_D3D11:
2065                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2066                 break;
2067         case RENDERPATH_GL20:
2068         case RENDERPATH_GLES2:
2069                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2070                 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);
2071                 break;
2072         case RENDERPATH_GL13:
2073         case RENDERPATH_GLES1:
2074                 R_Mesh_TexBind(0, 0);
2075                 R_Mesh_TexBind(1, 0);
2076                 break;
2077         case RENDERPATH_GL11:
2078                 R_Mesh_TexBind(0, 0);
2079                 break;
2080         case RENDERPATH_SOFT:
2081                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2082                 break;
2083         }
2084 }
2085
2086 extern qboolean r_shadow_usingdeferredprepass;
2087 extern rtexture_t *r_shadow_attenuationgradienttexture;
2088 extern rtexture_t *r_shadow_attenuation2dtexture;
2089 extern rtexture_t *r_shadow_attenuation3dtexture;
2090 extern qboolean r_shadow_usingshadowmap2d;
2091 extern qboolean r_shadow_usingshadowmaportho;
2092 extern float r_shadow_shadowmap_texturescale[2];
2093 extern float r_shadow_shadowmap_parameters[4];
2094 extern qboolean r_shadow_shadowmapvsdct;
2095 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2096 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2097 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2098 extern matrix4x4_t r_shadow_shadowmapmatrix;
2099 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2100 extern int r_shadow_prepass_width;
2101 extern int r_shadow_prepass_height;
2102 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2103 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2104 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2105 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2106
2107 #define BLENDFUNC_ALLOWS_COLORMOD      1
2108 #define BLENDFUNC_ALLOWS_FOG           2
2109 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2110 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2111 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2112 static int R_BlendFuncFlags(int src, int dst)
2113 {
2114         int r = 0;
2115
2116         // a blendfunc allows colormod if:
2117         // a) it can never keep the destination pixel invariant, or
2118         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2119         // this is to prevent unintended side effects from colormod
2120
2121         // a blendfunc allows fog if:
2122         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2123         // this is to prevent unintended side effects from fog
2124
2125         // these checks are the output of fogeval.pl
2126
2127         r |= BLENDFUNC_ALLOWS_COLORMOD;
2128         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2129         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2130         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2131         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2132         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2133         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2134         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2135         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2136         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2137         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2138         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2139         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2140         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2141         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2142         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2143         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2144         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2145         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2146         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2147         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2148         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2149
2150         return r;
2151 }
2152
2153 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)
2154 {
2155         // select a permutation of the lighting shader appropriate to this
2156         // combination of texture, entity, light source, and fogging, only use the
2157         // minimum features necessary to avoid wasting rendering time in the
2158         // fragment shader on features that are not being used
2159         unsigned int permutation = 0;
2160         unsigned int mode = 0;
2161         int blendfuncflags;
2162         static float dummy_colormod[3] = {1, 1, 1};
2163         float *colormod = rsurface.colormod;
2164         float m16f[16];
2165         matrix4x4_t tempmatrix;
2166         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2167         if (r_trippy.integer && !notrippy)
2168                 permutation |= SHADERPERMUTATION_TRIPPY;
2169         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2170                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2171         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2172                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2173         if (rsurfacepass == RSURFPASS_BACKGROUND)
2174         {
2175                 // distorted background
2176                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2177                 {
2178                         mode = SHADERMODE_WATER;
2179                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2180                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2181                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2182                         {
2183                                 // this is the right thing to do for wateralpha
2184                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2185                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2186                         }
2187                         else
2188                         {
2189                                 // this is the right thing to do for entity alpha
2190                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2191                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2192                         }
2193                 }
2194                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2195                 {
2196                         mode = SHADERMODE_REFRACTION;
2197                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2198                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2199                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2200                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2201                 }
2202                 else
2203                 {
2204                         mode = SHADERMODE_GENERIC;
2205                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2206                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2207                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2208                 }
2209                 if (vid.allowalphatocoverage)
2210                         GL_AlphaToCoverage(false);
2211         }
2212         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2213         {
2214                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2215                 {
2216                         switch(rsurface.texture->offsetmapping)
2217                         {
2218                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2219                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2220                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2221                         case OFFSETMAPPING_OFF: break;
2222                         }
2223                 }
2224                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2225                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2226                 // normalmap (deferred prepass), may use alpha test on diffuse
2227                 mode = SHADERMODE_DEFERREDGEOMETRY;
2228                 GL_BlendFunc(GL_ONE, GL_ZERO);
2229                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2230                 if (vid.allowalphatocoverage)
2231                         GL_AlphaToCoverage(false);
2232         }
2233         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2234         {
2235                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2236                 {
2237                         switch(rsurface.texture->offsetmapping)
2238                         {
2239                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2240                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242                         case OFFSETMAPPING_OFF: break;
2243                         }
2244                 }
2245                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2246                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2247                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2248                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2249                 // light source
2250                 mode = SHADERMODE_LIGHTSOURCE;
2251                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2252                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2253                 if (diffusescale > 0)
2254                         permutation |= SHADERPERMUTATION_DIFFUSE;
2255                 if (specularscale > 0)
2256                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2257                 if (r_refdef.fogenabled)
2258                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2259                 if (rsurface.texture->colormapping)
2260                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2261                 if (r_shadow_usingshadowmap2d)
2262                 {
2263                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2264                         if(r_shadow_shadowmapvsdct)
2265                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2266
2267                         if (r_shadow_shadowmap2ddepthbuffer)
2268                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2269                 }
2270                 if (rsurface.texture->reflectmasktexture)
2271                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2272                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2273                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2274                 if (vid.allowalphatocoverage)
2275                         GL_AlphaToCoverage(false);
2276         }
2277         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2278         {
2279                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2280                 {
2281                         switch(rsurface.texture->offsetmapping)
2282                         {
2283                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2284                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_OFF: break;
2287                         }
2288                 }
2289                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2290                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2291                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2292                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2293                 // unshaded geometry (fullbright or ambient model lighting)
2294                 mode = SHADERMODE_FLATCOLOR;
2295                 ambientscale = diffusescale = specularscale = 0;
2296                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2297                         permutation |= SHADERPERMUTATION_GLOW;
2298                 if (r_refdef.fogenabled)
2299                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2300                 if (rsurface.texture->colormapping)
2301                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2302                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2303                 {
2304                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2305                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2306
2307                         if (r_shadow_shadowmap2ddepthbuffer)
2308                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2309                 }
2310                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2311                         permutation |= SHADERPERMUTATION_REFLECTION;
2312                 if (rsurface.texture->reflectmasktexture)
2313                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2314                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2315                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2316                 // when using alphatocoverage, we don't need alphakill
2317                 if (vid.allowalphatocoverage)
2318                 {
2319                         if (r_transparent_alphatocoverage.integer)
2320                         {
2321                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2322                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2323                         }
2324                         else
2325                                 GL_AlphaToCoverage(false);
2326                 }
2327         }
2328         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2329         {
2330                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2331                 {
2332                         switch(rsurface.texture->offsetmapping)
2333                         {
2334                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2335                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2336                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2337                         case OFFSETMAPPING_OFF: break;
2338                         }
2339                 }
2340                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2341                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2342                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2343                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2344                 // directional model lighting
2345                 mode = SHADERMODE_LIGHTDIRECTION;
2346                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2347                         permutation |= SHADERPERMUTATION_GLOW;
2348                 permutation |= SHADERPERMUTATION_DIFFUSE;
2349                 if (specularscale > 0)
2350                         permutation |= SHADERPERMUTATION_SPECULAR;
2351                 if (r_refdef.fogenabled)
2352                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2353                 if (rsurface.texture->colormapping)
2354                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2355                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2356                 {
2357                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2358                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2359
2360                         if (r_shadow_shadowmap2ddepthbuffer)
2361                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2362                 }
2363                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2364                         permutation |= SHADERPERMUTATION_REFLECTION;
2365                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2366                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2367                 if (rsurface.texture->reflectmasktexture)
2368                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2369                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2370                 {
2371                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2372                         if (r_shadow_bouncegriddirectional)
2373                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2374                 }
2375                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2376                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2377                 // when using alphatocoverage, we don't need alphakill
2378                 if (vid.allowalphatocoverage)
2379                 {
2380                         if (r_transparent_alphatocoverage.integer)
2381                         {
2382                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2383                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2384                         }
2385                         else
2386                                 GL_AlphaToCoverage(false);
2387                 }
2388         }
2389         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2390         {
2391                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2392                 {
2393                         switch(rsurface.texture->offsetmapping)
2394                         {
2395                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2396                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2397                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2398                         case OFFSETMAPPING_OFF: break;
2399                         }
2400                 }
2401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2402                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2403                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2404                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2405                 // ambient model lighting
2406                 mode = SHADERMODE_LIGHTDIRECTION;
2407                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2408                         permutation |= SHADERPERMUTATION_GLOW;
2409                 if (r_refdef.fogenabled)
2410                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2411                 if (rsurface.texture->colormapping)
2412                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2413                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2414                 {
2415                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2416                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2417
2418                         if (r_shadow_shadowmap2ddepthbuffer)
2419                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2420                 }
2421                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2422                         permutation |= SHADERPERMUTATION_REFLECTION;
2423                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2424                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2425                 if (rsurface.texture->reflectmasktexture)
2426                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2427                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2428                 {
2429                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2430                         if (r_shadow_bouncegriddirectional)
2431                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2432                 }
2433                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2434                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435                 // when using alphatocoverage, we don't need alphakill
2436                 if (vid.allowalphatocoverage)
2437                 {
2438                         if (r_transparent_alphatocoverage.integer)
2439                         {
2440                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2441                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2442                         }
2443                         else
2444                                 GL_AlphaToCoverage(false);
2445                 }
2446         }
2447         else
2448         {
2449                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2450                 {
2451                         switch(rsurface.texture->offsetmapping)
2452                         {
2453                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2454                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2455                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2456                         case OFFSETMAPPING_OFF: break;
2457                         }
2458                 }
2459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2460                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2461                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2462                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2463                 // lightmapped wall
2464                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2465                         permutation |= SHADERPERMUTATION_GLOW;
2466                 if (r_refdef.fogenabled)
2467                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2468                 if (rsurface.texture->colormapping)
2469                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2470                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2471                 {
2472                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2473                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2474
2475                         if (r_shadow_shadowmap2ddepthbuffer)
2476                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2477                 }
2478                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2479                         permutation |= SHADERPERMUTATION_REFLECTION;
2480                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2481                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2482                 if (rsurface.texture->reflectmasktexture)
2483                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2484                 if (FAKELIGHT_ENABLED)
2485                 {
2486                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2487                         mode = SHADERMODE_FAKELIGHT;
2488                         permutation |= SHADERPERMUTATION_DIFFUSE;
2489                         if (specularscale > 0)
2490                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2491                 }
2492                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2493                 {
2494                         // deluxemapping (light direction texture)
2495                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2496                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2497                         else
2498                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2499                         permutation |= SHADERPERMUTATION_DIFFUSE;
2500                         if (specularscale > 0)
2501                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2502                 }
2503                 else if (r_glsl_deluxemapping.integer >= 2)
2504                 {
2505                         // fake deluxemapping (uniform light direction in tangentspace)
2506                         if (rsurface.uselightmaptexture)
2507                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2508                         else
2509                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2510                         permutation |= SHADERPERMUTATION_DIFFUSE;
2511                         if (specularscale > 0)
2512                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2513                 }
2514                 else if (rsurface.uselightmaptexture)
2515                 {
2516                         // ordinary lightmapping (q1bsp, q3bsp)
2517                         mode = SHADERMODE_LIGHTMAP;
2518                 }
2519                 else
2520                 {
2521                         // ordinary vertex coloring (q3bsp)
2522                         mode = SHADERMODE_VERTEXCOLOR;
2523                 }
2524                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2525                 {
2526                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2527                         if (r_shadow_bouncegriddirectional)
2528                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2529                 }
2530                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2531                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2532                 // when using alphatocoverage, we don't need alphakill
2533                 if (vid.allowalphatocoverage)
2534                 {
2535                         if (r_transparent_alphatocoverage.integer)
2536                         {
2537                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2538                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2539                         }
2540                         else
2541                                 GL_AlphaToCoverage(false);
2542                 }
2543         }
2544         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2545                 colormod = dummy_colormod;
2546         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2547                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2548         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2549                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2550         switch(vid.renderpath)
2551         {
2552         case RENDERPATH_D3D9:
2553 #ifdef SUPPORTD3D
2554                 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);
2555                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2556                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2557                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2558                 if (mode == SHADERMODE_LIGHTSOURCE)
2559                 {
2560                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2561                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2562                 }
2563                 else
2564                 {
2565                         if (mode == SHADERMODE_LIGHTDIRECTION)
2566                         {
2567                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2568                         }
2569                 }
2570                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2571                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2572                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2573                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2574                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2575
2576                 if (mode == SHADERMODE_LIGHTSOURCE)
2577                 {
2578                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2579                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2580                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2581                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2582                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2583
2584                         // additive passes are only darkened by fog, not tinted
2585                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2586                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2587                 }
2588                 else
2589                 {
2590                         if (mode == SHADERMODE_FLATCOLOR)
2591                         {
2592                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2593                         }
2594                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2595                         {
2596                                 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]);
2597                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2598                                 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);
2599                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2600                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2601                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2602                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2603                         }
2604                         else
2605                         {
2606                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2607                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2608                                 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);
2609                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2610                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2611                         }
2612                         // additive passes are only darkened by fog, not tinted
2613                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2614                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2615                         else
2616                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2617                         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);
2618                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2619                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2620                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2621                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2622                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2623                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2624                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2625                         if (mode == SHADERMODE_WATER)
2626                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2627                 }
2628                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2629                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2630                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2631                 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));
2632                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2633                 if (rsurface.texture->pantstexture)
2634                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2635                 else
2636                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2637                 if (rsurface.texture->shirttexture)
2638                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2639                 else
2640                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2641                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2642                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2643                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2644                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2645                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2646                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2647                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2648                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2649                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2650                         );
2651                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2652                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2653                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2654                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2655
2656                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2657                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2658                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2659                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2660                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2661                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2662                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2663                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2664                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2665                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2666                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2667                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2668                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2669                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2670                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2671                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2672                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2673                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2674                 {
2675                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2676                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2677                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2678                 }
2679                 else
2680                 {
2681                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2682                 }
2683 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2684                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2685                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2686                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2687                 {
2688                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2689                         if (rsurface.rtlight)
2690                         {
2691                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2692                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2693                         }
2694                 }
2695 #endif
2696                 break;
2697         case RENDERPATH_D3D10:
2698                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2699                 break;
2700         case RENDERPATH_D3D11:
2701                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2702                 break;
2703         case RENDERPATH_GL20:
2704         case RENDERPATH_GLES2:
2705                 if (!vid.useinterleavedarrays)
2706                 {
2707                         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);
2708                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2709                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2710                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2711                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2712                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2713                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2714                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2715                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2716                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2717                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2718                 }
2719                 else
2720                 {
2721                         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);
2722                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2723                 }
2724                 // this has to be after RSurf_PrepareVerticesForBatch
2725                 if (rsurface.batchskeletaltransform3x4buffer)
2726                         permutation |= SHADERPERMUTATION_SKELETAL;
2727                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2728                 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);
2729                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2730                 if (mode == SHADERMODE_LIGHTSOURCE)
2731                 {
2732                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2733                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2734                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2735                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2736                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2737                         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);
2738         
2739                         // additive passes are only darkened by fog, not tinted
2740                         if (r_glsl_permutation->loc_FogColor >= 0)
2741                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2742                         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);
2743                 }
2744                 else
2745                 {
2746                         if (mode == SHADERMODE_FLATCOLOR)
2747                         {
2748                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2749                         }
2750                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2751                         {
2752                                 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]);
2753                                 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]);
2754                                 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);
2755                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2756                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2757                                 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]);
2758                                 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]);
2759                         }
2760                         else
2761                         {
2762                                 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]);
2763                                 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]);
2764                                 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);
2765                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2766                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2767                         }
2768                         // additive passes are only darkened by fog, not tinted
2769                         if (r_glsl_permutation->loc_FogColor >= 0)
2770                         {
2771                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2772                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2773                                 else
2774                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2775                         }
2776                         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);
2777                         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]);
2778                         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]);
2779                         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]);
2780                         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]);
2781                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2782                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2783                         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);
2784                         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]);
2785                 }
2786                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2787                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2788                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2789                 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]);
2790                 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]);
2791
2792                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2793                 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));
2794                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2795                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2796                 {
2797                         if (rsurface.texture->pantstexture)
2798                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2799                         else
2800                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2801                 }
2802                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2803                 {
2804                         if (rsurface.texture->shirttexture)
2805                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2806                         else
2807                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2808                 }
2809                 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]);
2810                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2811                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2812                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2813                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2814                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2815                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2816                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2817                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2818                         );
2819                 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);
2820                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2821                 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]);
2822                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2823                 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);}
2824                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2825
2826                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2827                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2828                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2829                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2830                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2831                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2832                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2833                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2834                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2835                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2836                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2837                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2838                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2839                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2840                 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);
2841                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2842                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2843                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2844                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2845                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2846                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2847                 {
2848                         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);
2849                         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);
2850                         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);
2851                 }
2852                 else
2853                 {
2854                         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);
2855                 }
2856                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2857                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2858                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2859                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2860                 {
2861                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2862                         if (rsurface.rtlight)
2863                         {
2864                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2865                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2866                         }
2867                 }
2868                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2869                 CHECKGLERROR
2870                 break;
2871         case RENDERPATH_GL11:
2872         case RENDERPATH_GL13:
2873         case RENDERPATH_GLES1:
2874                 break;
2875         case RENDERPATH_SOFT:
2876                 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);
2877                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2878                 R_SetupShader_SetPermutationSoft(mode, permutation);
2879                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2880                 if (mode == SHADERMODE_LIGHTSOURCE)
2881                 {
2882                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2883                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2884                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2885                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2886                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2887                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2888         
2889                         // additive passes are only darkened by fog, not tinted
2890                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2891                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2892                 }
2893                 else
2894                 {
2895                         if (mode == SHADERMODE_FLATCOLOR)
2896                         {
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2898                         }
2899                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2900                         {
2901                                 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]);
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2903                                 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);
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2905                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2906                                 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]);
2907                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2908                         }
2909                         else
2910                         {
2911                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2912                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2913                                 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);
2914                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2915                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2916                         }
2917                         // additive passes are only darkened by fog, not tinted
2918                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2920                         else
2921                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2922                         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);
2923                         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]);
2924                         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]);
2925                         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]);
2926                         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]);
2927                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2928                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2929                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2930                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2931                 }
2932                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2933                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2934                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2935                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2936                 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]);
2937
2938                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2939                 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));
2940                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2941                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2942                 {
2943                         if (rsurface.texture->pantstexture)
2944                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2945                         else
2946                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2947                 }
2948                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2949                 {
2950                         if (rsurface.texture->shirttexture)
2951                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2952                         else
2953                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2954                 }
2955                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2956                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2957                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2958                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2959                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2960                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2961                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2962                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2963                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2964                         );
2965                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2966                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2967                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2968                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2969
2970                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2971                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2972                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2973                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2974                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2975                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2976                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2977                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2978                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2979                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2980                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2981                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2982                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2983                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2984                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2985                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2986                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2987                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2988                 {
2989                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2990                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2991                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2992                 }
2993                 else
2994                 {
2995                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2996                 }
2997 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2998                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2999                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3000                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3001                 {
3002                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3003                         if (rsurface.rtlight)
3004                         {
3005                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3006                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3007                         }
3008                 }
3009                 break;
3010         }
3011 }
3012
3013 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3014 {
3015         // select a permutation of the lighting shader appropriate to this
3016         // combination of texture, entity, light source, and fogging, only use the
3017         // minimum features necessary to avoid wasting rendering time in the
3018         // fragment shader on features that are not being used
3019         unsigned int permutation = 0;
3020         unsigned int mode = 0;
3021         const float *lightcolorbase = rtlight->currentcolor;
3022         float ambientscale = rtlight->ambientscale;
3023         float diffusescale = rtlight->diffusescale;
3024         float specularscale = rtlight->specularscale;
3025         // this is the location of the light in view space
3026         vec3_t viewlightorigin;
3027         // this transforms from view space (camera) to light space (cubemap)
3028         matrix4x4_t viewtolight;
3029         matrix4x4_t lighttoview;
3030         float viewtolight16f[16];
3031         // light source
3032         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3033         if (rtlight->currentcubemap != r_texture_whitecube)
3034                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3035         if (diffusescale > 0)
3036                 permutation |= SHADERPERMUTATION_DIFFUSE;
3037         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3038                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3039         if (r_shadow_usingshadowmap2d)
3040         {
3041                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3042                 if (r_shadow_shadowmapvsdct)
3043                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3044
3045                 if (r_shadow_shadowmap2ddepthbuffer)
3046                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3047         }
3048         if (vid.allowalphatocoverage)
3049                 GL_AlphaToCoverage(false);
3050         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3051         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3052         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3053         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3054         switch(vid.renderpath)
3055         {
3056         case RENDERPATH_D3D9:
3057 #ifdef SUPPORTD3D
3058                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3059                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3060                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3061                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3062                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3063                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3064                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3065                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3066                 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);
3067                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3068                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3069
3070                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3071                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3072                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3073                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3074                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3075 #endif
3076                 break;
3077         case RENDERPATH_D3D10:
3078                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3079                 break;
3080         case RENDERPATH_D3D11:
3081                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3082                 break;
3083         case RENDERPATH_GL20:
3084         case RENDERPATH_GLES2:
3085                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3086                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3087                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3088                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3089                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3090                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3091                 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]);
3092                 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]);
3093                 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);
3094                 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]);
3095                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3096
3097                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3098                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3099                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3100                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3101                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3102                 break;
3103         case RENDERPATH_GL11:
3104         case RENDERPATH_GL13:
3105         case RENDERPATH_GLES1:
3106                 break;
3107         case RENDERPATH_SOFT:
3108                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3109                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3110                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3111                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3112                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3113                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3114                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3115                 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]);
3116                 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);
3117                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3118                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3119
3120                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3121                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3122                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3123                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3124                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3125                 break;
3126         }
3127 }
3128
3129 #define SKINFRAME_HASH 1024
3130
3131 typedef struct
3132 {
3133         int loadsequence; // incremented each level change
3134         memexpandablearray_t array;
3135         skinframe_t *hash[SKINFRAME_HASH];
3136 }
3137 r_skinframe_t;
3138 r_skinframe_t r_skinframe;
3139
3140 void R_SkinFrame_PrepareForPurge(void)
3141 {
3142         r_skinframe.loadsequence++;
3143         // wrap it without hitting zero
3144         if (r_skinframe.loadsequence >= 200)
3145                 r_skinframe.loadsequence = 1;
3146 }
3147
3148 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3149 {
3150         if (!skinframe)
3151                 return;
3152         // mark the skinframe as used for the purging code
3153         skinframe->loadsequence = r_skinframe.loadsequence;
3154 }
3155
3156 void R_SkinFrame_Purge(void)
3157 {
3158         int i;
3159         skinframe_t *s;
3160         for (i = 0;i < SKINFRAME_HASH;i++)
3161         {
3162                 for (s = r_skinframe.hash[i];s;s = s->next)
3163                 {
3164                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3165                         {
3166                                 if (s->merged == s->base)
3167                                         s->merged = NULL;
3168                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3169                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3170                                 R_PurgeTexture(s->merged);s->merged = NULL;
3171                                 R_PurgeTexture(s->base  );s->base   = NULL;
3172                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3173                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3174                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3175                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3176                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3177                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3178                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3179                                 s->loadsequence = 0;
3180                         }
3181                 }
3182         }
3183 }
3184
3185 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3186         skinframe_t *item;
3187         char basename[MAX_QPATH];
3188
3189         Image_StripImageExtension(name, basename, sizeof(basename));
3190
3191         if( last == NULL ) {
3192                 int hashindex;
3193                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3194                 item = r_skinframe.hash[hashindex];
3195         } else {
3196                 item = last->next;
3197         }
3198
3199         // linearly search through the hash bucket
3200         for( ; item ; item = item->next ) {
3201                 if( !strcmp( item->basename, basename ) ) {
3202                         return item;
3203                 }
3204         }
3205         return NULL;
3206 }
3207
3208 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3209 {
3210         skinframe_t *item;
3211         int hashindex;
3212         char basename[MAX_QPATH];
3213
3214         Image_StripImageExtension(name, basename, sizeof(basename));
3215
3216         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3217         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3218                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3219                         break;
3220
3221         if (!item) {
3222                 rtexture_t *dyntexture;
3223                 // check whether its a dynamic texture
3224                 dyntexture = CL_GetDynTexture( basename );
3225                 if (!add && !dyntexture)
3226                         return NULL;
3227                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3228                 memset(item, 0, sizeof(*item));
3229                 strlcpy(item->basename, basename, sizeof(item->basename));
3230                 item->base = dyntexture; // either NULL or dyntexture handle
3231                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3232                 item->comparewidth = comparewidth;
3233                 item->compareheight = compareheight;
3234                 item->comparecrc = comparecrc;
3235                 item->next = r_skinframe.hash[hashindex];
3236                 r_skinframe.hash[hashindex] = item;
3237         }
3238         else if (textureflags & TEXF_FORCE_RELOAD)
3239         {
3240                 rtexture_t *dyntexture;
3241                 // check whether its a dynamic texture
3242                 dyntexture = CL_GetDynTexture( basename );
3243                 if (!add && !dyntexture)
3244                         return NULL;
3245                 if (item->merged == item->base)
3246                         item->merged = NULL;
3247                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3248                 R_PurgeTexture(item->stain );item->stain  = NULL;
3249                 R_PurgeTexture(item->merged);item->merged = NULL;
3250                 R_PurgeTexture(item->base  );item->base   = NULL;
3251                 R_PurgeTexture(item->pants );item->pants  = NULL;
3252                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3253                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3254                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3255                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3256                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3257         R_PurgeTexture(item->reflect);item->reflect = NULL;
3258                 item->loadsequence = 0;
3259         }
3260         else if( item->base == NULL )
3261         {
3262                 rtexture_t *dyntexture;
3263                 // check whether its a dynamic texture
3264                 // 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]
3265                 dyntexture = CL_GetDynTexture( basename );
3266                 item->base = dyntexture; // either NULL or dyntexture handle
3267         }
3268
3269         R_SkinFrame_MarkUsed(item);
3270         return item;
3271 }
3272
3273 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3274         { \
3275                 unsigned long long avgcolor[5], wsum; \
3276                 int pix, comp, w; \
3277                 avgcolor[0] = 0; \
3278                 avgcolor[1] = 0; \
3279                 avgcolor[2] = 0; \
3280                 avgcolor[3] = 0; \
3281                 avgcolor[4] = 0; \
3282                 wsum = 0; \
3283                 for(pix = 0; pix < cnt; ++pix) \
3284                 { \
3285                         w = 0; \
3286                         for(comp = 0; comp < 3; ++comp) \
3287                                 w += getpixel; \
3288                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3289                         { \
3290                                 ++wsum; \
3291                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3292                                 w = getpixel; \
3293                                 for(comp = 0; comp < 3; ++comp) \
3294                                         avgcolor[comp] += getpixel * w; \
3295                                 avgcolor[3] += w; \
3296                         } \
3297                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3298                         avgcolor[4] += getpixel; \
3299                 } \
3300                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3301                         avgcolor[3] = 1; \
3302                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3303                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3304                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3305                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3306         }
3307
3308 extern cvar_t gl_picmip;
3309 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3310 {
3311         int j;
3312         unsigned char *pixels;
3313         unsigned char *bumppixels;
3314         unsigned char *basepixels = NULL;
3315         int basepixels_width = 0;
3316         int basepixels_height = 0;
3317         skinframe_t *skinframe;
3318         rtexture_t *ddsbase = NULL;
3319         qboolean ddshasalpha = false;
3320         float ddsavgcolor[4];
3321         char basename[MAX_QPATH];
3322         int miplevel = R_PicmipForFlags(textureflags);
3323         int savemiplevel = miplevel;
3324         int mymiplevel;
3325         char vabuf[1024];
3326
3327         if (cls.state == ca_dedicated)
3328                 return NULL;
3329
3330         // return an existing skinframe if already loaded
3331         // if loading of the first image fails, don't make a new skinframe as it
3332         // would cause all future lookups of this to be missing
3333         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3334         if (skinframe && skinframe->base)
3335                 return skinframe;
3336
3337         Image_StripImageExtension(name, basename, sizeof(basename));
3338
3339         // check for DDS texture file first
3340         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3341         {
3342                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3343                 if (basepixels == NULL)
3344                         return NULL;
3345         }
3346
3347         // FIXME handle miplevel
3348
3349         if (developer_loading.integer)
3350                 Con_Printf("loading skin \"%s\"\n", name);
3351
3352         // we've got some pixels to store, so really allocate this new texture now
3353         if (!skinframe)
3354                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3355         textureflags &= ~TEXF_FORCE_RELOAD;
3356         skinframe->stain = NULL;
3357         skinframe->merged = NULL;
3358         skinframe->base = NULL;
3359         skinframe->pants = NULL;
3360         skinframe->shirt = NULL;
3361         skinframe->nmap = NULL;
3362         skinframe->gloss = NULL;
3363         skinframe->glow = NULL;
3364         skinframe->fog = NULL;
3365         skinframe->reflect = NULL;
3366         skinframe->hasalpha = false;
3367
3368         if (ddsbase)
3369         {
3370                 skinframe->base = ddsbase;
3371                 skinframe->hasalpha = ddshasalpha;
3372                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3373                 if (r_loadfog && skinframe->hasalpha)
3374                         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);
3375                 //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]);
3376         }
3377         else
3378         {
3379                 basepixels_width = image_width;
3380                 basepixels_height = image_height;
3381                 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);
3382                 if (textureflags & TEXF_ALPHA)
3383                 {
3384                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3385                         {
3386                                 if (basepixels[j] < 255)
3387                                 {
3388                                         skinframe->hasalpha = true;
3389                                         break;
3390                                 }
3391                         }
3392                         if (r_loadfog && skinframe->hasalpha)
3393                         {
3394                                 // has transparent pixels
3395                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3396                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3397                                 {
3398                                         pixels[j+0] = 255;
3399                                         pixels[j+1] = 255;
3400                                         pixels[j+2] = 255;
3401                                         pixels[j+3] = basepixels[j+3];
3402                                 }
3403                                 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);
3404                                 Mem_Free(pixels);
3405                         }
3406                 }
3407                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3408 #ifndef USE_GLES2
3409                 //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]);
3410                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3411                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3412                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3413                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3414 #endif
3415         }
3416
3417         if (r_loaddds)
3418         {
3419                 mymiplevel = savemiplevel;
3420                 if (r_loadnormalmap)
3421                         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);
3422                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3423                 if (r_loadgloss)
3424                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3425                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3426                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3427                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3428         }
3429
3430         // _norm is the name used by tenebrae and has been adopted as standard
3431         if (r_loadnormalmap && skinframe->nmap == NULL)
3432         {
3433                 mymiplevel = savemiplevel;
3434                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3435                 {
3436                         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);
3437                         Mem_Free(pixels);
3438                         pixels = NULL;
3439                 }
3440                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3441                 {
3442                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3443                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3444                         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);
3445                         Mem_Free(pixels);
3446                         Mem_Free(bumppixels);
3447                 }
3448                 else if (r_shadow_bumpscale_basetexture.value > 0)
3449                 {
3450                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3451                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3452                         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);
3453                         Mem_Free(pixels);
3454                 }
3455 #ifndef USE_GLES2
3456                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3457                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3458 #endif
3459         }
3460
3461         // _luma is supported only for tenebrae compatibility
3462         // _glow is the preferred name
3463         mymiplevel = savemiplevel;
3464         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))))
3465         {
3466                 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);
3467 #ifndef USE_GLES2
3468                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3469                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3470 #endif
3471                 Mem_Free(pixels);pixels = NULL;
3472         }
3473
3474         mymiplevel = savemiplevel;
3475         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3476         {
3477                 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);
3478 #ifndef USE_GLES2
3479                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3480                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3481 #endif
3482                 Mem_Free(pixels);
3483                 pixels = NULL;
3484         }
3485
3486         mymiplevel = savemiplevel;
3487         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3488         {
3489                 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);
3490 #ifndef USE_GLES2
3491                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3492                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3493 #endif
3494                 Mem_Free(pixels);
3495                 pixels = NULL;
3496         }
3497
3498         mymiplevel = savemiplevel;
3499         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3500         {
3501                 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);
3502 #ifndef USE_GLES2
3503                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3504                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3505 #endif
3506                 Mem_Free(pixels);
3507                 pixels = NULL;
3508         }
3509
3510         mymiplevel = savemiplevel;
3511         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3512         {
3513                 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);
3514 #ifndef USE_GLES2
3515                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3516                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3517 #endif
3518                 Mem_Free(pixels);
3519                 pixels = NULL;
3520         }
3521
3522         if (basepixels)
3523                 Mem_Free(basepixels);
3524
3525         return skinframe;
3526 }
3527
3528 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3529 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3530 {
3531         int i;
3532         unsigned char *temp1, *temp2;
3533         skinframe_t *skinframe;
3534         char vabuf[1024];
3535
3536         if (cls.state == ca_dedicated)
3537                 return NULL;
3538
3539         // if already loaded just return it, otherwise make a new skinframe
3540         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3541         if (skinframe->base)
3542                 return skinframe;
3543         textureflags &= ~TEXF_FORCE_RELOAD;
3544
3545         skinframe->stain = NULL;
3546         skinframe->merged = NULL;
3547         skinframe->base = NULL;
3548         skinframe->pants = NULL;
3549         skinframe->shirt = NULL;
3550         skinframe->nmap = NULL;
3551         skinframe->gloss = NULL;
3552         skinframe->glow = NULL;
3553         skinframe->fog = NULL;
3554         skinframe->reflect = NULL;
3555         skinframe->hasalpha = false;
3556
3557         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3558         if (!skindata)
3559                 return NULL;
3560
3561         if (developer_loading.integer)
3562                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3563
3564         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3565         {
3566                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3567                 temp2 = temp1 + width * height * 4;
3568                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3569                 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);
3570                 Mem_Free(temp1);
3571         }
3572         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3573         if (textureflags & TEXF_ALPHA)
3574         {
3575                 for (i = 3;i < width * height * 4;i += 4)
3576                 {
3577                         if (skindata[i] < 255)
3578                         {
3579                                 skinframe->hasalpha = true;
3580                                 break;
3581                         }
3582                 }
3583                 if (r_loadfog && skinframe->hasalpha)
3584                 {
3585                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3586                         memcpy(fogpixels, skindata, width * height * 4);
3587                         for (i = 0;i < width * height * 4;i += 4)
3588                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3589                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3590                         Mem_Free(fogpixels);
3591                 }
3592         }
3593
3594         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3595         //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]);
3596
3597         return skinframe;
3598 }
3599
3600 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3601 {
3602         int i;
3603         int featuresmask;
3604         skinframe_t *skinframe;
3605
3606         if (cls.state == ca_dedicated)
3607                 return NULL;
3608
3609         // if already loaded just return it, otherwise make a new skinframe
3610         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3611         if (skinframe->base)
3612                 return skinframe;
3613         //textureflags &= ~TEXF_FORCE_RELOAD;
3614
3615         skinframe->stain = NULL;
3616         skinframe->merged = NULL;
3617         skinframe->base = NULL;
3618         skinframe->pants = NULL;
3619         skinframe->shirt = NULL;
3620         skinframe->nmap = NULL;
3621         skinframe->gloss = NULL;
3622         skinframe->glow = NULL;
3623         skinframe->fog = NULL;
3624         skinframe->reflect = NULL;
3625         skinframe->hasalpha = false;
3626
3627         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3628         if (!skindata)
3629                 return NULL;
3630
3631         if (developer_loading.integer)
3632                 Con_Printf("loading quake skin \"%s\"\n", name);
3633
3634         // 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)
3635         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3636         memcpy(skinframe->qpixels, skindata, width*height);
3637         skinframe->qwidth = width;
3638         skinframe->qheight = height;
3639
3640         featuresmask = 0;
3641         for (i = 0;i < width * height;i++)
3642                 featuresmask |= palette_featureflags[skindata[i]];
3643
3644         skinframe->hasalpha = false;
3645         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3646         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3647         skinframe->qgeneratemerged = true;
3648         skinframe->qgeneratebase = skinframe->qhascolormapping;
3649         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3650
3651         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3652         //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]);
3653
3654         return skinframe;
3655 }
3656
3657 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3658 {
3659         int width;
3660         int height;
3661         unsigned char *skindata;
3662         char vabuf[1024];
3663
3664         if (!skinframe->qpixels)
3665                 return;
3666
3667         if (!skinframe->qhascolormapping)
3668                 colormapped = false;
3669
3670         if (colormapped)
3671         {
3672                 if (!skinframe->qgeneratebase)
3673                         return;
3674         }
3675         else
3676         {
3677                 if (!skinframe->qgeneratemerged)
3678                         return;
3679         }
3680
3681         width = skinframe->qwidth;
3682         height = skinframe->qheight;
3683         skindata = skinframe->qpixels;
3684
3685         if (skinframe->qgeneratenmap)
3686         {
3687                 unsigned char *temp1, *temp2;
3688                 skinframe->qgeneratenmap = false;
3689                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3690                 temp2 = temp1 + width * height * 4;
3691                 // use either a custom palette or the quake palette
3692                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3693                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3694                 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);
3695                 Mem_Free(temp1);
3696         }
3697
3698         if (skinframe->qgenerateglow)
3699         {
3700                 skinframe->qgenerateglow = false;
3701                 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
3702         }
3703
3704         if (colormapped)
3705         {
3706                 skinframe->qgeneratebase = false;
3707                 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);
3708                 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);
3709                 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);
3710         }
3711         else
3712         {
3713                 skinframe->qgeneratemerged = false;
3714                 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);
3715         }
3716
3717         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3718         {
3719                 Mem_Free(skinframe->qpixels);
3720                 skinframe->qpixels = NULL;
3721         }
3722 }
3723
3724 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)
3725 {
3726         int i;
3727         skinframe_t *skinframe;
3728         char vabuf[1024];
3729
3730         if (cls.state == ca_dedicated)
3731                 return NULL;
3732
3733         // if already loaded just return it, otherwise make a new skinframe
3734         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3735         if (skinframe->base)
3736                 return skinframe;
3737         textureflags &= ~TEXF_FORCE_RELOAD;
3738
3739         skinframe->stain = NULL;
3740         skinframe->merged = NULL;
3741         skinframe->base = NULL;
3742         skinframe->pants = NULL;
3743         skinframe->shirt = NULL;
3744         skinframe->nmap = NULL;
3745         skinframe->gloss = NULL;
3746         skinframe->glow = NULL;
3747         skinframe->fog = NULL;
3748         skinframe->reflect = NULL;
3749         skinframe->hasalpha = false;
3750
3751         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3752         if (!skindata)
3753                 return NULL;
3754
3755         if (developer_loading.integer)
3756                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3757
3758         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3759         if (textureflags & TEXF_ALPHA)
3760         {
3761                 for (i = 0;i < width * height;i++)
3762                 {
3763                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3764                         {
3765                                 skinframe->hasalpha = true;
3766                                 break;
3767                         }
3768                 }
3769                 if (r_loadfog && skinframe->hasalpha)
3770                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3771         }
3772
3773         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3774         //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]);
3775
3776         return skinframe;
3777 }
3778
3779 skinframe_t *R_SkinFrame_LoadMissing(void)
3780 {
3781         skinframe_t *skinframe;
3782
3783         if (cls.state == ca_dedicated)
3784                 return NULL;
3785
3786         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3787         skinframe->stain = NULL;
3788         skinframe->merged = NULL;
3789         skinframe->base = NULL;
3790         skinframe->pants = NULL;
3791         skinframe->shirt = NULL;
3792         skinframe->nmap = NULL;
3793         skinframe->gloss = NULL;
3794         skinframe->glow = NULL;
3795         skinframe->fog = NULL;
3796         skinframe->reflect = NULL;
3797         skinframe->hasalpha = false;
3798
3799         skinframe->avgcolor[0] = rand() / RAND_MAX;
3800         skinframe->avgcolor[1] = rand() / RAND_MAX;
3801         skinframe->avgcolor[2] = rand() / RAND_MAX;
3802         skinframe->avgcolor[3] = 1;
3803
3804         return skinframe;
3805 }
3806
3807 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3808 typedef struct suffixinfo_s
3809 {
3810         const char *suffix;
3811         qboolean flipx, flipy, flipdiagonal;
3812 }
3813 suffixinfo_t;
3814 static suffixinfo_t suffix[3][6] =
3815 {
3816         {
3817                 {"px",   false, false, false},
3818                 {"nx",   false, false, false},
3819                 {"py",   false, false, false},
3820                 {"ny",   false, false, false},
3821                 {"pz",   false, false, false},
3822                 {"nz",   false, false, false}
3823         },
3824         {
3825                 {"posx", false, false, false},
3826                 {"negx", false, false, false},
3827                 {"posy", false, false, false},
3828                 {"negy", false, false, false},
3829                 {"posz", false, false, false},
3830                 {"negz", false, false, false}
3831         },
3832         {
3833                 {"rt",    true, false,  true},
3834                 {"lf",   false,  true,  true},
3835                 {"ft",    true,  true, false},
3836                 {"bk",   false, false, false},
3837                 {"up",    true, false,  true},
3838                 {"dn",    true, false,  true}
3839         }
3840 };
3841
3842 static int componentorder[4] = {0, 1, 2, 3};
3843
3844 static rtexture_t *R_LoadCubemap(const char *basename)
3845 {
3846         int i, j, cubemapsize;
3847         unsigned char *cubemappixels, *image_buffer;
3848         rtexture_t *cubemaptexture;
3849         char name[256];
3850         // must start 0 so the first loadimagepixels has no requested width/height
3851         cubemapsize = 0;
3852         cubemappixels = NULL;
3853         cubemaptexture = NULL;
3854         // keep trying different suffix groups (posx, px, rt) until one loads
3855         for (j = 0;j < 3 && !cubemappixels;j++)
3856         {
3857                 // load the 6 images in the suffix group
3858                 for (i = 0;i < 6;i++)
3859                 {
3860                         // generate an image name based on the base and and suffix
3861                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3862                         // load it
3863                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3864                         {
3865                                 // an image loaded, make sure width and height are equal
3866                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3867                                 {
3868                                         // if this is the first image to load successfully, allocate the cubemap memory
3869                                         if (!cubemappixels && image_width >= 1)
3870                                         {
3871                                                 cubemapsize = image_width;
3872                                                 // note this clears to black, so unavailable sides are black
3873                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3874                                         }
3875                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3876                                         if (cubemappixels)
3877                                                 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);
3878                                 }
3879                                 else
3880                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3881                                 // free the image
3882                                 Mem_Free(image_buffer);
3883                         }
3884                 }
3885         }
3886         // if a cubemap loaded, upload it
3887         if (cubemappixels)
3888         {
3889                 if (developer_loading.integer)
3890                         Con_Printf("loading cubemap \"%s\"\n", basename);
3891
3892                 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);
3893                 Mem_Free(cubemappixels);
3894         }
3895         else
3896         {
3897                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3898                 if (developer_loading.integer)
3899                 {
3900                         Con_Printf("(tried tried images ");
3901                         for (j = 0;j < 3;j++)
3902                                 for (i = 0;i < 6;i++)
3903                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3904                         Con_Print(" and was unable to find any of them).\n");
3905                 }
3906         }
3907         return cubemaptexture;
3908 }
3909
3910 rtexture_t *R_GetCubemap(const char *basename)
3911 {
3912         int i;
3913         for (i = 0;i < r_texture_numcubemaps;i++)
3914                 if (r_texture_cubemaps[i] != NULL)
3915                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3916                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3917         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3918                 return r_texture_whitecube;
3919         r_texture_numcubemaps++;
3920         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3921         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3922         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3923         return r_texture_cubemaps[i]->texture;
3924 }
3925
3926 static void R_Main_FreeViewCache(void)
3927 {
3928         if (r_refdef.viewcache.entityvisible)
3929                 Mem_Free(r_refdef.viewcache.entityvisible);
3930         if (r_refdef.viewcache.world_pvsbits)
3931                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3932         if (r_refdef.viewcache.world_leafvisible)
3933                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3934         if (r_refdef.viewcache.world_surfacevisible)
3935                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3936         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3937 }
3938
3939 static void R_Main_ResizeViewCache(void)
3940 {
3941         int numentities = r_refdef.scene.numentities;
3942         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3943         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3944         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3945         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3946         if (r_refdef.viewcache.maxentities < numentities)
3947         {
3948                 r_refdef.viewcache.maxentities = numentities;
3949                 if (r_refdef.viewcache.entityvisible)
3950                         Mem_Free(r_refdef.viewcache.entityvisible);
3951                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3952         }
3953         if (r_refdef.viewcache.world_numclusters != numclusters)
3954         {
3955                 r_refdef.viewcache.world_numclusters = numclusters;
3956                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3957                 if (r_refdef.viewcache.world_pvsbits)
3958                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3959                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3960         }
3961         if (r_refdef.viewcache.world_numleafs != numleafs)
3962         {
3963                 r_refdef.viewcache.world_numleafs = numleafs;
3964                 if (r_refdef.viewcache.world_leafvisible)
3965                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3966                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3967         }
3968         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3969         {
3970                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3971                 if (r_refdef.viewcache.world_surfacevisible)
3972                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3973                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3974         }
3975 }
3976
3977 extern rtexture_t *loadingscreentexture;
3978 static void gl_main_start(void)
3979 {
3980         loadingscreentexture = NULL;
3981         r_texture_blanknormalmap = NULL;
3982         r_texture_white = NULL;
3983         r_texture_grey128 = NULL;
3984         r_texture_black = NULL;
3985         r_texture_whitecube = NULL;
3986         r_texture_normalizationcube = NULL;
3987         r_texture_fogattenuation = NULL;
3988         r_texture_fogheighttexture = NULL;
3989         r_texture_gammaramps = NULL;
3990         r_texture_numcubemaps = 0;
3991         r_uniformbufferalignment = 32;
3992
3993         r_loaddds = r_texture_dds_load.integer != 0;
3994         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3995
3996         switch(vid.renderpath)
3997         {
3998         case RENDERPATH_GL20:
3999         case RENDERPATH_D3D9:
4000         case RENDERPATH_D3D10:
4001         case RENDERPATH_D3D11:
4002         case RENDERPATH_SOFT:
4003         case RENDERPATH_GLES2:
4004                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4005                 Cvar_SetValueQuick(&gl_combine, 1);
4006                 Cvar_SetValueQuick(&r_glsl, 1);
4007                 r_loadnormalmap = true;
4008                 r_loadgloss = true;
4009                 r_loadfog = false;
4010                 if (vid.support.arb_uniform_buffer_object)
4011                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4012                 break;
4013         case RENDERPATH_GL13:
4014         case RENDERPATH_GLES1:
4015                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4016                 Cvar_SetValueQuick(&gl_combine, 1);
4017                 Cvar_SetValueQuick(&r_glsl, 0);
4018                 r_loadnormalmap = false;
4019                 r_loadgloss = false;
4020                 r_loadfog = true;
4021                 break;
4022         case RENDERPATH_GL11:
4023                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4024                 Cvar_SetValueQuick(&gl_combine, 0);
4025                 Cvar_SetValueQuick(&r_glsl, 0);
4026                 r_loadnormalmap = false;
4027                 r_loadgloss = false;
4028                 r_loadfog = true;
4029                 break;
4030         }
4031
4032         R_AnimCache_Free();
4033         R_FrameData_Reset();
4034         R_BufferData_Reset();
4035
4036         r_numqueries = 0;
4037         r_maxqueries = 0;
4038         memset(r_queries, 0, sizeof(r_queries));
4039
4040         r_qwskincache = NULL;
4041         r_qwskincache_size = 0;
4042
4043         // due to caching of texture_t references, the collision cache must be reset
4044         Collision_Cache_Reset(true);
4045
4046         // set up r_skinframe loading system for textures
4047         memset(&r_skinframe, 0, sizeof(r_skinframe));
4048         r_skinframe.loadsequence = 1;
4049         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4050
4051         r_main_texturepool = R_AllocTexturePool();
4052         R_BuildBlankTextures();
4053         R_BuildNoTexture();
4054         if (vid.support.arb_texture_cube_map)
4055         {
4056                 R_BuildWhiteCube();
4057                 R_BuildNormalizationCube();
4058         }
4059         r_texture_fogattenuation = NULL;
4060         r_texture_fogheighttexture = NULL;
4061         r_texture_gammaramps = NULL;
4062         //r_texture_fogintensity = NULL;
4063         memset(&r_fb, 0, sizeof(r_fb));
4064         r_glsl_permutation = NULL;
4065         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4066         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4067         glslshaderstring = NULL;
4068 #ifdef SUPPORTD3D
4069         r_hlsl_permutation = NULL;
4070         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4071         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4072 #endif
4073         hlslshaderstring = NULL;
4074         memset(&r_svbsp, 0, sizeof (r_svbsp));
4075
4076         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4077         r_texture_numcubemaps = 0;
4078
4079         r_refdef.fogmasktable_density = 0;
4080 }
4081
4082 static void gl_main_shutdown(void)
4083 {
4084         R_AnimCache_Free();
4085         R_FrameData_Reset();
4086         R_BufferData_Reset();
4087
4088         R_Main_FreeViewCache();
4089
4090         switch(vid.renderpath)
4091         {
4092         case RENDERPATH_GL11:
4093         case RENDERPATH_GL13:
4094         case RENDERPATH_GL20:
4095         case RENDERPATH_GLES1:
4096         case RENDERPATH_GLES2:
4097 #ifdef GL_SAMPLES_PASSED_ARB
4098                 if (r_maxqueries)
4099                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4100 #endif
4101                 break;
4102         case RENDERPATH_D3D9:
4103                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4104                 break;
4105         case RENDERPATH_D3D10:
4106                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4107                 break;
4108         case RENDERPATH_D3D11:
4109                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4110                 break;
4111         case RENDERPATH_SOFT:
4112                 break;
4113         }
4114
4115         r_numqueries = 0;
4116         r_maxqueries = 0;
4117         memset(r_queries, 0, sizeof(r_queries));
4118
4119         r_qwskincache = NULL;
4120         r_qwskincache_size = 0;
4121
4122         // clear out the r_skinframe state
4123         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4124         memset(&r_skinframe, 0, sizeof(r_skinframe));
4125
4126         if (r_svbsp.nodes)
4127                 Mem_Free(r_svbsp.nodes);
4128         memset(&r_svbsp, 0, sizeof (r_svbsp));
4129         R_FreeTexturePool(&r_main_texturepool);
4130         loadingscreentexture = NULL;
4131         r_texture_blanknormalmap = NULL;
4132         r_texture_white = NULL;
4133         r_texture_grey128 = NULL;
4134         r_texture_black = NULL;
4135         r_texture_whitecube = NULL;
4136         r_texture_normalizationcube = NULL;
4137         r_texture_fogattenuation = NULL;
4138         r_texture_fogheighttexture = NULL;
4139         r_texture_gammaramps = NULL;
4140         r_texture_numcubemaps = 0;
4141         //r_texture_fogintensity = NULL;
4142         memset(&r_fb, 0, sizeof(r_fb));
4143         R_GLSL_Restart_f();
4144
4145         r_glsl_permutation = NULL;
4146         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4147         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4148         glslshaderstring = NULL;
4149 #ifdef SUPPORTD3D
4150         r_hlsl_permutation = NULL;
4151         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4152         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4153 #endif
4154         hlslshaderstring = NULL;
4155 }
4156
4157 static void gl_main_newmap(void)
4158 {
4159         // FIXME: move this code to client
4160         char *entities, entname[MAX_QPATH];
4161         if (r_qwskincache)
4162                 Mem_Free(r_qwskincache);
4163         r_qwskincache = NULL;
4164         r_qwskincache_size = 0;
4165         if (cl.worldmodel)
4166         {
4167                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4168                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4169                 {
4170                         CL_ParseEntityLump(entities);
4171                         Mem_Free(entities);
4172                         return;
4173                 }
4174                 if (cl.worldmodel->brush.entities)
4175                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4176         }
4177         R_Main_FreeViewCache();
4178
4179         R_FrameData_Reset();
4180         R_BufferData_Reset();
4181 }
4182
4183 void GL_Main_Init(void)
4184 {
4185         int i;
4186         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4187
4188         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4189         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4190         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4191         if (gamemode == GAME_NEHAHRA)
4192         {
4193                 Cvar_RegisterVariable (&gl_fogenable);
4194                 Cvar_RegisterVariable (&gl_fogdensity);
4195                 Cvar_RegisterVariable (&gl_fogred);
4196                 Cvar_RegisterVariable (&gl_foggreen);
4197                 Cvar_RegisterVariable (&gl_fogblue);
4198                 Cvar_RegisterVariable (&gl_fogstart);
4199                 Cvar_RegisterVariable (&gl_fogend);
4200                 Cvar_RegisterVariable (&gl_skyclip);
4201         }
4202         Cvar_RegisterVariable(&r_motionblur);
4203         Cvar_RegisterVariable(&r_damageblur);
4204         Cvar_RegisterVariable(&r_motionblur_averaging);
4205         Cvar_RegisterVariable(&r_motionblur_randomize);
4206         Cvar_RegisterVariable(&r_motionblur_minblur);
4207         Cvar_RegisterVariable(&r_motionblur_maxblur);
4208         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4209         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4210         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4211         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4212         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4213         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4214         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4215         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4216         Cvar_RegisterVariable(&r_equalize_entities_by);
4217         Cvar_RegisterVariable(&r_equalize_entities_to);
4218         Cvar_RegisterVariable(&r_depthfirst);
4219         Cvar_RegisterVariable(&r_useinfinitefarclip);
4220         Cvar_RegisterVariable(&r_farclip_base);
4221         Cvar_RegisterVariable(&r_farclip_world);
4222         Cvar_RegisterVariable(&r_nearclip);
4223         Cvar_RegisterVariable(&r_deformvertexes);
4224         Cvar_RegisterVariable(&r_transparent);
4225         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4226         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4227         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4228         Cvar_RegisterVariable(&r_showoverdraw);
4229         Cvar_RegisterVariable(&r_showbboxes);
4230         Cvar_RegisterVariable(&r_showsurfaces);
4231         Cvar_RegisterVariable(&r_showtris);
4232         Cvar_RegisterVariable(&r_shownormals);
4233         Cvar_RegisterVariable(&r_showlighting);
4234         Cvar_RegisterVariable(&r_showshadowvolumes);
4235         Cvar_RegisterVariable(&r_showcollisionbrushes);
4236         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4237         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4238         Cvar_RegisterVariable(&r_showdisabledepthtest);
4239         Cvar_RegisterVariable(&r_drawportals);
4240         Cvar_RegisterVariable(&r_drawentities);
4241         Cvar_RegisterVariable(&r_draw2d);
4242         Cvar_RegisterVariable(&r_drawworld);
4243         Cvar_RegisterVariable(&r_cullentities_trace);
4244         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4245         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4246         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4247         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4248         Cvar_RegisterVariable(&r_sortentities);
4249         Cvar_RegisterVariable(&r_drawviewmodel);
4250         Cvar_RegisterVariable(&r_drawexteriormodel);
4251         Cvar_RegisterVariable(&r_speeds);
4252         Cvar_RegisterVariable(&r_fullbrights);
4253         Cvar_RegisterVariable(&r_wateralpha);
4254         Cvar_RegisterVariable(&r_dynamic);
4255         Cvar_RegisterVariable(&r_fakelight);
4256         Cvar_RegisterVariable(&r_fakelight_intensity);
4257         Cvar_RegisterVariable(&r_fullbright);
4258         Cvar_RegisterVariable(&r_shadows);
4259         Cvar_RegisterVariable(&r_shadows_darken);
4260         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4261         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4262         Cvar_RegisterVariable(&r_shadows_throwdistance);
4263         Cvar_RegisterVariable(&r_shadows_throwdirection);
4264         Cvar_RegisterVariable(&r_shadows_focus);
4265         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4266         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4267         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4268         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4269         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4270         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4271         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4272         Cvar_RegisterVariable(&r_fog_exp2);
4273         Cvar_RegisterVariable(&r_fog_clear);
4274         Cvar_RegisterVariable(&r_drawfog);
4275         Cvar_RegisterVariable(&r_transparentdepthmasking);
4276         Cvar_RegisterVariable(&r_transparent_sortmindist);
4277         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4278         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4279         Cvar_RegisterVariable(&r_texture_dds_load);
4280         Cvar_RegisterVariable(&r_texture_dds_save);
4281         Cvar_RegisterVariable(&r_textureunits);
4282         Cvar_RegisterVariable(&gl_combine);
4283         Cvar_RegisterVariable(&r_usedepthtextures);
4284         Cvar_RegisterVariable(&r_viewfbo);
4285         Cvar_RegisterVariable(&r_viewscale);
4286         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4287         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4288         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4289         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4290         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4291         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4292         Cvar_RegisterVariable(&r_glsl);
4293         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4294         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4295         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4296         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4297         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4298         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4299         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4300         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4301         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4302         Cvar_RegisterVariable(&r_glsl_postprocess);
4303         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4304         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4305         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4306         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4307         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4308         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4309         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4310         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4311         Cvar_RegisterVariable(&r_celshading);
4312         Cvar_RegisterVariable(&r_celoutlines);
4313
4314         Cvar_RegisterVariable(&r_water);
4315         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4316         Cvar_RegisterVariable(&r_water_clippingplanebias);
4317         Cvar_RegisterVariable(&r_water_refractdistort);
4318         Cvar_RegisterVariable(&r_water_reflectdistort);
4319         Cvar_RegisterVariable(&r_water_scissormode);
4320         Cvar_RegisterVariable(&r_water_lowquality);
4321         Cvar_RegisterVariable(&r_water_hideplayer);
4322         Cvar_RegisterVariable(&r_water_fbo);
4323
4324         Cvar_RegisterVariable(&r_lerpsprites);
4325         Cvar_RegisterVariable(&r_lerpmodels);
4326         Cvar_RegisterVariable(&r_lerplightstyles);
4327         Cvar_RegisterVariable(&r_waterscroll);
4328         Cvar_RegisterVariable(&r_bloom);
4329         Cvar_RegisterVariable(&r_bloom_colorscale);
4330         Cvar_RegisterVariable(&r_bloom_brighten);
4331         Cvar_RegisterVariable(&r_bloom_blur);
4332         Cvar_RegisterVariable(&r_bloom_resolution);
4333         Cvar_RegisterVariable(&r_bloom_colorexponent);
4334         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4335         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4336         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4337         Cvar_RegisterVariable(&r_hdr_glowintensity);
4338         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4339         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4340         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4341         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4342         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4343         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4344         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4345         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4346         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4347         Cvar_RegisterVariable(&developer_texturelogging);
4348         Cvar_RegisterVariable(&gl_lightmaps);
4349         Cvar_RegisterVariable(&r_test);
4350         Cvar_RegisterVariable(&r_batch_multidraw);
4351         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4352         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4353         Cvar_RegisterVariable(&r_glsl_skeletal);
4354         Cvar_RegisterVariable(&r_glsl_saturation);
4355         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4356         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4357         Cvar_RegisterVariable(&r_framedatasize);
4358         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4359                 Cvar_RegisterVariable(&r_buffermegs[i]);
4360         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4361         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4362                 Cvar_SetValue("r_fullbrights", 0);
4363         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4364 }
4365
4366 void Render_Init(void)
4367 {
4368         gl_backend_init();
4369         R_Textures_Init();
4370         GL_Main_Init();
4371         Font_Init();
4372         GL_Draw_Init();
4373         R_Shadow_Init();
4374         R_Sky_Init();
4375         GL_Surf_Init();
4376         Sbar_Init();
4377         R_Particles_Init();
4378         R_Explosion_Init();
4379         R_LightningBeams_Init();
4380         Mod_RenderInit();
4381 }
4382
4383 /*
4384 ===============
4385 GL_Init
4386 ===============
4387 */
4388 #ifndef USE_GLES2
4389 extern char *ENGINE_EXTENSIONS;
4390 void GL_Init (void)
4391 {
4392         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4393         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4394         gl_version = (const char *)qglGetString(GL_VERSION);
4395         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4396
4397         if (!gl_extensions)
4398                 gl_extensions = "";
4399         if (!gl_platformextensions)
4400                 gl_platformextensions = "";
4401
4402         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4403         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4404         Con_Printf("GL_VERSION: %s\n", gl_version);
4405         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4406         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4407
4408         VID_CheckExtensions();
4409
4410         // LordHavoc: report supported extensions
4411         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4412
4413         // clear to black (loading plaque will be seen over this)
4414         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4415 }
4416 #endif
4417
4418 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4419 {
4420         int i;
4421         mplane_t *p;
4422         if (r_trippy.integer)
4423                 return false;
4424         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4425         {
4426                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4427                 if (i == 4)
4428                         continue;
4429                 p = r_refdef.view.frustum + i;
4430                 switch(p->signbits)
4431                 {
4432                 default:
4433                 case 0:
4434                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 1:
4438                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 2:
4442                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 3:
4446                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 4:
4450                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 case 5:
4454                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4455                                 return true;
4456                         break;
4457                 case 6:
4458                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4459                                 return true;
4460                         break;
4461                 case 7:
4462                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4463                                 return true;
4464                         break;
4465                 }
4466         }
4467         return false;
4468 }
4469
4470 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4471 {
4472         int i;
4473         const mplane_t *p;
4474         if (r_trippy.integer)
4475                 return false;
4476         for (i = 0;i < numplanes;i++)
4477         {
4478                 p = planes + i;
4479                 switch(p->signbits)
4480                 {
4481                 default:
4482                 case 0:
4483                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4484                                 return true;
4485                         break;
4486                 case 1:
4487                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4488                                 return true;
4489                         break;
4490                 case 2:
4491                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 case 3:
4495                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4496                                 return true;
4497                         break;
4498                 case 4:
4499                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4500                                 return true;
4501                         break;
4502                 case 5:
4503                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4504                                 return true;
4505                         break;
4506                 case 6:
4507                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4508                                 return true;
4509                         break;
4510                 case 7:
4511                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4512                                 return true;
4513                         break;
4514                 }
4515         }
4516         return false;
4517 }
4518
4519 //==================================================================================
4520
4521 // LordHavoc: this stores temporary data used within the same frame
4522
4523 typedef struct r_framedata_mem_s
4524 {
4525         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4526         size_t size; // how much usable space
4527         size_t current; // how much space in use
4528         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4529         size_t wantedsize; // how much space was allocated
4530         unsigned char *data; // start of real data (16byte aligned)
4531 }
4532 r_framedata_mem_t;
4533
4534 static r_framedata_mem_t *r_framedata_mem;
4535
4536 void R_FrameData_Reset(void)
4537 {
4538         while (r_framedata_mem)
4539         {
4540                 r_framedata_mem_t *next = r_framedata_mem->purge;
4541                 Mem_Free(r_framedata_mem);
4542                 r_framedata_mem = next;
4543         }
4544 }
4545
4546 static void R_FrameData_Resize(qboolean mustgrow)
4547 {
4548         size_t wantedsize;
4549         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4550         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4551         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4552         {
4553                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4554                 newmem->wantedsize = wantedsize;
4555                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4556                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4557                 newmem->current = 0;
4558                 newmem->mark = 0;
4559                 newmem->purge = r_framedata_mem;
4560                 r_framedata_mem = newmem;
4561         }
4562 }
4563
4564 void R_FrameData_NewFrame(void)
4565 {
4566         R_FrameData_Resize(false);
4567         if (!r_framedata_mem)
4568                 return;
4569         // if we ran out of space on the last frame, free the old memory now
4570         while (r_framedata_mem->purge)
4571         {
4572                 // repeatedly remove the second item in the list, leaving only head
4573                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4574                 Mem_Free(r_framedata_mem->purge);
4575                 r_framedata_mem->purge = next;
4576         }
4577         // reset the current mem pointer
4578         r_framedata_mem->current = 0;
4579         r_framedata_mem->mark = 0;
4580 }
4581
4582 void *R_FrameData_Alloc(size_t size)
4583 {
4584         void *data;
4585         float newvalue;
4586
4587         // align to 16 byte boundary - the data pointer is already aligned, so we
4588         // only need to ensure the size of every allocation is also aligned
4589         size = (size + 15) & ~15;
4590
4591         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4592         {
4593                 // emergency - we ran out of space, allocate more memory
4594                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4595                 // this might not be a growing it, but we'll allocate another buffer every time
4596                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4597                 R_FrameData_Resize(true);
4598         }
4599
4600         data = r_framedata_mem->data + r_framedata_mem->current;
4601         r_framedata_mem->current += size;
4602
4603         // count the usage for stats
4604         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4605         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4606
4607         return (void *)data;
4608 }
4609
4610 void *R_FrameData_Store(size_t size, void *data)
4611 {
4612         void *d = R_FrameData_Alloc(size);
4613         if (d && data)
4614                 memcpy(d, data, size);
4615         return d;
4616 }
4617
4618 void R_FrameData_SetMark(void)
4619 {
4620         if (!r_framedata_mem)
4621                 return;
4622         r_framedata_mem->mark = r_framedata_mem->current;
4623 }
4624
4625 void R_FrameData_ReturnToMark(void)
4626 {
4627         if (!r_framedata_mem)
4628                 return;
4629         r_framedata_mem->current = r_framedata_mem->mark;
4630 }
4631
4632 //==================================================================================
4633
4634 // avoid reusing the same buffer objects on consecutive frames
4635 #define R_BUFFERDATA_CYCLE 3
4636
4637 typedef struct r_bufferdata_buffer_s
4638 {
4639         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4640         size_t size; // how much usable space
4641         size_t current; // how much space in use
4642         r_meshbuffer_t *buffer; // the buffer itself
4643 }
4644 r_bufferdata_buffer_t;
4645
4646 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4647 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4648
4649 /// frees all dynamic buffers
4650 void R_BufferData_Reset(void)
4651 {
4652         int cycle, type;
4653         r_bufferdata_buffer_t **p, *mem;
4654         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4655         {
4656                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4657                 {
4658                         // free all buffers
4659                         p = &r_bufferdata_buffer[cycle][type];
4660                         while (*p)
4661                         {
4662                                 mem = *p;
4663                                 *p = (*p)->purge;
4664                                 if (mem->buffer)
4665                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4666                                 Mem_Free(mem);
4667                         }
4668                 }
4669         }
4670 }
4671
4672 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4673 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4674 {
4675         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4676         size_t size;
4677         float newvalue = r_buffermegs[type].value;
4678
4679         // increase the cvar if we have to (but only if we already have a mem)
4680         if (mustgrow && mem)
4681                 newvalue *= 2.0f;
4682         newvalue = bound(0.25f, newvalue, 256.0f);
4683         while (newvalue * 1024*1024 < minsize)
4684                 newvalue *= 2.0f;
4685
4686         // clamp the cvar to valid range
4687         newvalue = bound(0.25f, newvalue, 256.0f);
4688         if (r_buffermegs[type].value != newvalue)
4689                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4690
4691         // calculate size in bytes
4692         size = (size_t)(newvalue * 1024*1024);
4693         size = bound(131072, size, 256*1024*1024);
4694
4695         // allocate a new buffer if the size is different (purge old one later)
4696         // or if we were told we must grow the buffer
4697         if (!mem || mem->size != size || mustgrow)
4698         {
4699                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4700                 mem->size = size;
4701                 mem->current = 0;
4702                 if (type == R_BUFFERDATA_VERTEX)
4703                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4704                 else if (type == R_BUFFERDATA_INDEX16)
4705                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4706                 else if (type == R_BUFFERDATA_INDEX32)
4707                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4708                 else if (type == R_BUFFERDATA_UNIFORM)
4709                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4710                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4711                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4712         }
4713 }
4714
4715 void R_BufferData_NewFrame(void)
4716 {
4717         int type;
4718         r_bufferdata_buffer_t **p, *mem;
4719         // cycle to the next frame's buffers
4720         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4721         // if we ran out of space on the last time we used these buffers, free the old memory now
4722         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4723         {
4724                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4725                 {
4726                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4727                         // free all but the head buffer, this is how we recycle obsolete
4728                         // buffers after they are no longer in use
4729                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4730                         while (*p)
4731                         {
4732                                 mem = *p;
4733                                 *p = (*p)->purge;
4734                                 if (mem->buffer)
4735                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4736                                 Mem_Free(mem);
4737                         }
4738                         // reset the current offset
4739                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4740                 }
4741         }
4742 }
4743
4744 r_meshbuffer_t *R_BufferData_Store(size_t datasize, void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4745 {
4746         r_bufferdata_buffer_t *mem;
4747         int offset = 0;
4748         int padsize;
4749
4750         *returnbufferoffset = 0;
4751
4752         // align size to a byte boundary appropriate for the buffer type, this
4753         // makes all allocations have aligned start offsets
4754         if (type == R_BUFFERDATA_UNIFORM)
4755                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4756         else
4757                 padsize = (datasize + 15) & ~15;
4758
4759         // if we ran out of space in this buffer we must allocate a new one
4760         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)
4761                 R_BufferData_Resize(type, true, padsize);
4762
4763         // if the resize did not give us enough memory, fail
4764         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)
4765                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4766
4767         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4768         offset = mem->current;
4769         mem->current += padsize;
4770
4771         // upload the data to the buffer at the chosen offset
4772         if (offset == 0)
4773                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4774         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4775
4776         // count the usage for stats
4777         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4778         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4779
4780         // return the buffer offset
4781         *returnbufferoffset = offset;
4782
4783         return mem->buffer;
4784 }
4785
4786 //==================================================================================
4787
4788 // LordHavoc: animcache originally written by Echon, rewritten since then
4789
4790 /**
4791  * Animation cache prevents re-generating mesh data for an animated model
4792  * multiple times in one frame for lighting, shadowing, reflections, etc.
4793  */
4794
4795 void R_AnimCache_Free(void)
4796 {
4797 }
4798
4799 void R_AnimCache_ClearCache(void)
4800 {
4801         int i;
4802         entity_render_t *ent;
4803
4804         for (i = 0;i < r_refdef.scene.numentities;i++)
4805         {
4806                 ent = r_refdef.scene.entities[i];
4807                 ent->animcache_vertex3f = NULL;
4808                 ent->animcache_vertex3f_vertexbuffer = NULL;
4809                 ent->animcache_vertex3f_bufferoffset = 0;
4810                 ent->animcache_normal3f = NULL;
4811                 ent->animcache_normal3f_vertexbuffer = NULL;
4812                 ent->animcache_normal3f_bufferoffset = 0;
4813                 ent->animcache_svector3f = NULL;
4814                 ent->animcache_svector3f_vertexbuffer = NULL;
4815                 ent->animcache_svector3f_bufferoffset = 0;
4816                 ent->animcache_tvector3f = NULL;
4817                 ent->animcache_tvector3f_vertexbuffer = NULL;
4818                 ent->animcache_tvector3f_bufferoffset = 0;
4819                 ent->animcache_vertexmesh = NULL;
4820                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4821                 ent->animcache_vertexmesh_bufferoffset = 0;
4822                 ent->animcache_skeletaltransform3x4 = NULL;
4823                 ent->animcache_skeletaltransform3x4buffer = NULL;
4824                 ent->animcache_skeletaltransform3x4offset = 0;
4825                 ent->animcache_skeletaltransform3x4size = 0;
4826         }
4827 }
4828
4829 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4830 {
4831         int i;
4832
4833         // check if we need the meshbuffers
4834         if (!vid.useinterleavedarrays)
4835                 return;
4836
4837         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4838                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4839         // TODO: upload vertexbuffer?
4840         if (ent->animcache_vertexmesh)
4841         {
4842                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4843                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4844                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4845                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4846                 for (i = 0;i < numvertices;i++)
4847                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4848                 if (ent->animcache_svector3f)
4849                         for (i = 0;i < numvertices;i++)
4850                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4851                 if (ent->animcache_tvector3f)
4852                         for (i = 0;i < numvertices;i++)
4853                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4854                 if (ent->animcache_normal3f)
4855                         for (i = 0;i < numvertices;i++)
4856                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4857         }
4858 }
4859
4860 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4861 {
4862         dp_model_t *model = ent->model;
4863         int numvertices;
4864
4865         // see if this ent is worth caching
4866         if (!model || !model->Draw || !model->AnimateVertices)
4867                 return false;
4868         // nothing to cache if it contains no animations and has no skeleton
4869         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4870                 return false;
4871         // see if it is already cached for gpuskeletal
4872         if (ent->animcache_skeletaltransform3x4)
4873                 return false;
4874         // see if it is already cached as a mesh
4875         if (ent->animcache_vertex3f)
4876         {
4877                 // check if we need to add normals or tangents
4878                 if (ent->animcache_normal3f)
4879                         wantnormals = false;
4880                 if (ent->animcache_svector3f)
4881                         wanttangents = false;
4882                 if (!wantnormals && !wanttangents)
4883                         return false;
4884         }
4885
4886         // check which kind of cache we need to generate
4887         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4888         {
4889                 // cache the skeleton so the vertex shader can use it
4890                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4891                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4892                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4893                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4894                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4895                 // note: this can fail if the buffer is at the grow limit
4896                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4897                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4898         }
4899         else if (ent->animcache_vertex3f)
4900         {
4901                 // mesh was already cached but we may need to add normals/tangents
4902                 // (this only happens with multiple views, reflections, cameras, etc)
4903                 if (wantnormals || wanttangents)
4904                 {
4905                         numvertices = model->surfmesh.num_vertices;
4906                         if (wantnormals)
4907                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4908                         if (wanttangents)
4909                         {
4910                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4911                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4912                         }
4913                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4914                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4915                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4916                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4917                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4918                 }
4919         }
4920         else
4921         {
4922                 // generate mesh cache
4923                 numvertices = model->surfmesh.num_vertices;
4924                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4925                 if (wantnormals)
4926                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4927                 if (wanttangents)
4928                 {
4929                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4930                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4931                 }
4932                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4933                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4934                 if (wantnormals || wanttangents)
4935                 {
4936                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4937                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4938                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4939                 }
4940                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4941                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4942                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4943         }
4944         return true;
4945 }
4946
4947 void R_AnimCache_CacheVisibleEntities(void)
4948 {
4949         int i;
4950         qboolean wantnormals = true;
4951         qboolean wanttangents = !r_showsurfaces.integer;
4952
4953         switch(vid.renderpath)
4954         {
4955         case RENDERPATH_GL20:
4956         case RENDERPATH_D3D9:
4957         case RENDERPATH_D3D10:
4958         case RENDERPATH_D3D11:
4959         case RENDERPATH_GLES2:
4960                 break;
4961         case RENDERPATH_GL11:
4962         case RENDERPATH_GL13:
4963         case RENDERPATH_GLES1:
4964                 wanttangents = false;
4965                 break;
4966         case RENDERPATH_SOFT:
4967                 break;
4968         }
4969
4970         if (r_shownormals.integer)
4971                 wanttangents = wantnormals = true;
4972
4973         // TODO: thread this
4974         // NOTE: R_PrepareRTLights() also caches entities
4975
4976         for (i = 0;i < r_refdef.scene.numentities;i++)
4977                 if (r_refdef.viewcache.entityvisible[i])
4978                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4979 }
4980
4981 //==================================================================================
4982
4983 extern cvar_t r_overheadsprites_pushback;
4984
4985 static void R_View_UpdateEntityLighting (void)
4986 {
4987         int i;
4988         entity_render_t *ent;
4989         vec3_t tempdiffusenormal, avg;
4990         vec_t f, fa, fd, fdd;
4991         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4992
4993         for (i = 0;i < r_refdef.scene.numentities;i++)
4994         {
4995                 ent = r_refdef.scene.entities[i];
4996
4997                 // skip unseen models
4998                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4999                         continue;
5000
5001                 // skip bsp models
5002                 if (ent->model && ent->model == cl.worldmodel)
5003                 {
5004                         // TODO: use modellight for r_ambient settings on world?
5005                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5006                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5007                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5008                         continue;
5009                 }
5010                 
5011                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5012                 {
5013                         // aleady updated by CSQC
5014                         // TODO: force modellight on BSP models in this case?
5015                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5016                 }
5017                 else
5018                 {
5019                         // fetch the lighting from the worldmodel data
5020                         VectorClear(ent->modellight_ambient);
5021                         VectorClear(ent->modellight_diffuse);
5022                         VectorClear(tempdiffusenormal);
5023                         if (ent->flags & RENDER_LIGHT)
5024                         {
5025                                 vec3_t org;
5026                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5027
5028                                 // complete lightning for lit sprites
5029                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5030                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5031                                 {
5032                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5033                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5034                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5035                                 }
5036                                 else
5037                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5038
5039                                 if(ent->flags & RENDER_EQUALIZE)
5040                                 {
5041                                         // first fix up ambient lighting...
5042                                         if(r_equalize_entities_minambient.value > 0)
5043                                         {
5044                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5045                                                 if(fd > 0)
5046                                                 {
5047                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5048                                                         if(fa < r_equalize_entities_minambient.value * fd)
5049                                                         {
5050                                                                 // solve:
5051                                                                 //   fa'/fd' = minambient
5052                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5053                                                                 //   ...
5054                                                                 //   fa' = fd' * minambient
5055                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5056                                                                 //   ...
5057                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5058                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5059                                                                 //   ...
5060                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5061                                                                 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
5062                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5063                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5064                                                         }
5065                                                 }
5066                                         }
5067
5068                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5069                                         {
5070                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5071                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5072                                                 f = fa + 0.25 * fd;
5073                                                 if(f > 0)
5074                                                 {
5075                                                         // adjust brightness and saturation to target
5076                                                         avg[0] = avg[1] = avg[2] = fa / f;
5077                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5078                                                         avg[0] = avg[1] = avg[2] = fd / f;
5079                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5080                                                 }
5081                                         }
5082                                 }
5083                         }
5084                         else // highly rare
5085                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5086                 }
5087
5088                 // move the light direction into modelspace coordinates for lighting code
5089                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5090                 if(VectorLength2(ent->modellight_lightdir) == 0)
5091                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5092                 VectorNormalize(ent->modellight_lightdir);
5093         }
5094 }
5095
5096 #define MAX_LINEOFSIGHTTRACES 64
5097
5098 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5099 {
5100         int i;
5101         vec3_t boxmins, boxmaxs;
5102         vec3_t start;
5103         vec3_t end;
5104         dp_model_t *model = r_refdef.scene.worldmodel;
5105
5106         if (!model || !model->brush.TraceLineOfSight)
5107                 return true;
5108
5109         // expand the box a little
5110         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5111         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5112         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5113         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5114         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5115         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5116
5117         // return true if eye is inside enlarged box
5118         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5119                 return true;
5120
5121         // try center
5122         VectorCopy(eye, start);
5123         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5124         if (model->brush.TraceLineOfSight(model, start, end))
5125                 return true;
5126
5127         // try various random positions
5128         for (i = 0;i < numsamples;i++)
5129         {
5130                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5131                 if (model->brush.TraceLineOfSight(model, start, end))
5132                         return true;
5133         }
5134
5135         return false;
5136 }
5137
5138
5139 static void R_View_UpdateEntityVisible (void)
5140 {
5141         int i;
5142         int renderimask;
5143         int samples;
5144         entity_render_t *ent;
5145
5146         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5147                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5148                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5149                 :                                                          RENDER_EXTERIORMODEL;
5150         if (!r_drawviewmodel.integer)
5151                 renderimask |= RENDER_VIEWMODEL;
5152         if (!r_drawexteriormodel.integer)
5153                 renderimask |= RENDER_EXTERIORMODEL;
5154         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5155         {
5156                 // worldmodel can check visibility
5157                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5158                 for (i = 0;i < r_refdef.scene.numentities;i++)
5159                 {
5160                         ent = r_refdef.scene.entities[i];
5161                         if (!(ent->flags & renderimask))
5162                         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)))
5163                         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))
5164                                 r_refdef.viewcache.entityvisible[i] = true;
5165                 }
5166         }
5167         else
5168         {
5169                 // no worldmodel or it can't check visibility
5170                 for (i = 0;i < r_refdef.scene.numentities;i++)
5171                 {
5172                         ent = r_refdef.scene.entities[i];
5173                         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));
5174                 }
5175         }
5176         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5177                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5178         {
5179                 for (i = 0;i < r_refdef.scene.numentities;i++)
5180                 {
5181                         if (!r_refdef.viewcache.entityvisible[i])
5182                                 continue;
5183                         ent = r_refdef.scene.entities[i];
5184                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5185                         {
5186                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5187                                 if (samples < 0)
5188                                         continue; // temp entities do pvs only
5189                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5190                                         ent->last_trace_visibility = realtime;
5191                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5192                                         r_refdef.viewcache.entityvisible[i] = 0;
5193                         }
5194                 }
5195         }
5196 }
5197
5198 /// only used if skyrendermasked, and normally returns false
5199 static int R_DrawBrushModelsSky (void)
5200 {
5201         int i, sky;
5202         entity_render_t *ent;
5203
5204         sky = false;
5205         for (i = 0;i < r_refdef.scene.numentities;i++)
5206         {
5207                 if (!r_refdef.viewcache.entityvisible[i])
5208                         continue;
5209                 ent = r_refdef.scene.entities[i];
5210                 if (!ent->model || !ent->model->DrawSky)
5211                         continue;
5212                 ent->model->DrawSky(ent);
5213                 sky = true;
5214         }
5215         return sky;
5216 }
5217
5218 static void R_DrawNoModel(entity_render_t *ent);
5219 static void R_DrawModels(void)
5220 {
5221         int i;
5222         entity_render_t *ent;
5223
5224         for (i = 0;i < r_refdef.scene.numentities;i++)
5225         {
5226                 if (!r_refdef.viewcache.entityvisible[i])
5227                         continue;
5228                 ent = r_refdef.scene.entities[i];
5229                 r_refdef.stats[r_stat_entities]++;
5230                 /*
5231                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5232                 {
5233                         vec3_t f, l, u, o;
5234                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5235                         Con_Printf("R_DrawModels\n");
5236                         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]);
5237                         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);
5238                         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);
5239                 }
5240                 */
5241                 if (ent->model && ent->model->Draw != NULL)
5242                         ent->model->Draw(ent);
5243                 else
5244                         R_DrawNoModel(ent);
5245         }
5246 }
5247
5248 static void R_DrawModelsDepth(void)
5249 {
5250         int i;
5251         entity_render_t *ent;
5252
5253         for (i = 0;i < r_refdef.scene.numentities;i++)
5254         {
5255                 if (!r_refdef.viewcache.entityvisible[i])
5256                         continue;
5257                 ent = r_refdef.scene.entities[i];
5258                 if (ent->model && ent->model->DrawDepth != NULL)
5259                         ent->model->DrawDepth(ent);
5260         }
5261 }
5262
5263 static void R_DrawModelsDebug(void)
5264 {
5265         int i;
5266         entity_render_t *ent;
5267
5268         for (i = 0;i < r_refdef.scene.numentities;i++)
5269         {
5270                 if (!r_refdef.viewcache.entityvisible[i])
5271                         continue;
5272                 ent = r_refdef.scene.entities[i];
5273                 if (ent->model && ent->model->DrawDebug != NULL)
5274                         ent->model->DrawDebug(ent);
5275         }
5276 }
5277
5278 static void R_DrawModelsAddWaterPlanes(void)
5279 {
5280         int i;
5281         entity_render_t *ent;
5282
5283         for (i = 0;i < r_refdef.scene.numentities;i++)
5284         {
5285                 if (!r_refdef.viewcache.entityvisible[i])
5286                         continue;
5287                 ent = r_refdef.scene.entities[i];
5288                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5289                         ent->model->DrawAddWaterPlanes(ent);
5290         }
5291 }
5292
5293 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}};
5294
5295 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5296 {
5297         if (r_hdr_irisadaptation.integer)
5298         {
5299                 vec3_t p;
5300                 vec3_t ambient;
5301                 vec3_t diffuse;
5302                 vec3_t diffusenormal;
5303                 vec3_t forward;
5304                 vec_t brightness = 0.0f;
5305                 vec_t goal;
5306                 vec_t current;
5307                 vec_t d;
5308                 int c;
5309                 VectorCopy(r_refdef.view.forward, forward);
5310                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5311                 {
5312                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5313                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5314                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5315                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5316                         d = DotProduct(forward, diffusenormal);
5317                         brightness += VectorLength(ambient);
5318                         if (d > 0)
5319                                 brightness += d * VectorLength(diffuse);
5320                 }
5321                 brightness *= 1.0f / c;
5322                 brightness += 0.00001f; // make sure it's never zero
5323                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5324                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5325                 current = r_hdr_irisadaptation_value.value;
5326                 if (current < goal)
5327                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5328                 else if (current > goal)
5329                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5330                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5331                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5332         }
5333         else if (r_hdr_irisadaptation_value.value != 1.0f)
5334                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5335 }
5336
5337 static void R_View_SetFrustum(const int *scissor)
5338 {
5339         int i;
5340         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5341         vec3_t forward, left, up, origin, v;
5342
5343         if(scissor)
5344         {
5345                 // flipped x coordinates (because x points left here)
5346                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5347                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5348
5349                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5350                 switch(vid.renderpath)
5351                 {
5352                         case RENDERPATH_D3D9:
5353                         case RENDERPATH_D3D10:
5354                         case RENDERPATH_D3D11:
5355                                 // non-flipped y coordinates
5356                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5357                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5358                                 break;
5359                         case RENDERPATH_SOFT:
5360                         case RENDERPATH_GL11:
5361                         case RENDERPATH_GL13:
5362                         case RENDERPATH_GL20:
5363                         case RENDERPATH_GLES1:
5364                         case RENDERPATH_GLES2:
5365                                 // non-flipped y coordinates
5366                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5367                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5368                                 break;
5369                 }
5370         }
5371
5372         // we can't trust r_refdef.view.forward and friends in reflected scenes
5373         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5374
5375 #if 0
5376         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5377         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5378         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5379         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5380         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5381         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5382         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5383         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5384         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5385         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5386         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5387         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5388 #endif
5389
5390 #if 0
5391         zNear = r_refdef.nearclip;
5392         nudge = 1.0 - 1.0 / (1<<23);
5393         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5394         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5395         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5396         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5397         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5398         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5399         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5400         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5401 #endif
5402
5403
5404
5405 #if 0
5406         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5407         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5408         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5409         r_refdef.view.frustum[0].dist = m[15] - m[12];
5410
5411         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5412         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5413         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5414         r_refdef.view.frustum[1].dist = m[15] + m[12];
5415
5416         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5417         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5418         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5419         r_refdef.view.frustum[2].dist = m[15] - m[13];
5420
5421         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5422         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5423         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5424         r_refdef.view.frustum[3].dist = m[15] + m[13];
5425
5426         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5427         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5428         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5429         r_refdef.view.frustum[4].dist = m[15] - m[14];
5430
5431         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5432         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5433         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5434         r_refdef.view.frustum[5].dist = m[15] + m[14];
5435 #endif
5436
5437         if (r_refdef.view.useperspective)
5438         {
5439                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5440                 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]);
5441                 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]);
5442                 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]);
5443                 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]);
5444
5445                 // then the normals from the corners relative to origin
5446                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5447                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5448                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5449                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5450
5451                 // in a NORMAL view, forward cross left == up
5452                 // in a REFLECTED view, forward cross left == down
5453                 // so our cross products above need to be adjusted for a left handed coordinate system
5454                 CrossProduct(forward, left, v);
5455                 if(DotProduct(v, up) < 0)
5456                 {
5457                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5458                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5459                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5460                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5461                 }
5462
5463                 // Leaving those out was a mistake, those were in the old code, and they
5464                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5465                 // I couldn't reproduce it after adding those normalizations. --blub
5466                 VectorNormalize(r_refdef.view.frustum[0].normal);
5467                 VectorNormalize(r_refdef.view.frustum[1].normal);
5468                 VectorNormalize(r_refdef.view.frustum[2].normal);
5469                 VectorNormalize(r_refdef.view.frustum[3].normal);
5470
5471                 // make the corners absolute
5472                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5473                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5474                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5475                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5476
5477                 // one more normal
5478                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5479
5480                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5481                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5482                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5483                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5484                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5485         }
5486         else
5487         {
5488                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5489                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5490                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5491                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5492                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5493                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5494                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5495                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5496                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5497                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5498         }
5499         r_refdef.view.numfrustumplanes = 5;
5500
5501         if (r_refdef.view.useclipplane)
5502         {
5503                 r_refdef.view.numfrustumplanes = 6;
5504                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5505         }
5506
5507         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5508                 PlaneClassify(r_refdef.view.frustum + i);
5509
5510         // LordHavoc: note to all quake engine coders, Quake had a special case
5511         // for 90 degrees which assumed a square view (wrong), so I removed it,
5512         // Quake2 has it disabled as well.
5513
5514         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5515         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5516         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5517         //PlaneClassify(&frustum[0]);
5518
5519         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5520         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5521         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5522         //PlaneClassify(&frustum[1]);
5523
5524         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5525         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5526         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5527         //PlaneClassify(&frustum[2]);
5528
5529         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5530         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5531         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5532         //PlaneClassify(&frustum[3]);
5533
5534         // nearclip plane
5535         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5536         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5537         //PlaneClassify(&frustum[4]);
5538 }
5539
5540 static void R_View_UpdateWithScissor(const int *myscissor)
5541 {
5542         R_Main_ResizeViewCache();
5543         R_View_SetFrustum(myscissor);
5544         R_View_WorldVisibility(r_refdef.view.useclipplane);
5545         R_View_UpdateEntityVisible();
5546         R_View_UpdateEntityLighting();
5547 }
5548
5549 static void R_View_Update(void)
5550 {
5551         R_Main_ResizeViewCache();
5552         R_View_SetFrustum(NULL);
5553         R_View_WorldVisibility(r_refdef.view.useclipplane);
5554         R_View_UpdateEntityVisible();
5555         R_View_UpdateEntityLighting();
5556 }
5557
5558 float viewscalefpsadjusted = 1.0f;
5559
5560 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5561 {
5562         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5563         scale = bound(0.03125f, scale, 1.0f);
5564         *outwidth = (int)ceil(width * scale);
5565         *outheight = (int)ceil(height * scale);
5566 }
5567
5568 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5569 {
5570         const float *customclipplane = NULL;
5571         float plane[4];
5572         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5573         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5574         {
5575                 // LordHavoc: couldn't figure out how to make this approach the
5576                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5577                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5578                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5579                         dist = r_refdef.view.clipplane.dist;
5580                 plane[0] = r_refdef.view.clipplane.normal[0];
5581                 plane[1] = r_refdef.view.clipplane.normal[1];
5582                 plane[2] = r_refdef.view.clipplane.normal[2];
5583                 plane[3] = -dist;
5584                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5585         }
5586
5587         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5588         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5589
5590         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5591         if (!r_refdef.view.useperspective)
5592                 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);
5593         else if (vid.stencil && r_useinfinitefarclip.integer)
5594                 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);
5595         else
5596                 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);
5597         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5598         R_SetViewport(&r_refdef.view.viewport);
5599         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5600         {
5601                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5602                 float screenplane[4];
5603                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5604                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5605                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5606                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5607                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5608         }
5609 }
5610
5611 void R_EntityMatrix(const matrix4x4_t *matrix)
5612 {
5613         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5614         {
5615                 gl_modelmatrixchanged = false;
5616                 gl_modelmatrix = *matrix;
5617                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5618                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5619                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5620                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5621                 CHECKGLERROR
5622                 switch(vid.renderpath)
5623                 {
5624                 case RENDERPATH_D3D9:
5625 #ifdef SUPPORTD3D
5626                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5627                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5628 #endif
5629                         break;
5630                 case RENDERPATH_D3D10:
5631                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5632                         break;
5633                 case RENDERPATH_D3D11:
5634                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5635                         break;
5636                 case RENDERPATH_GL11:
5637                 case RENDERPATH_GL13:
5638                 case RENDERPATH_GLES1:
5639                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5640                         break;
5641                 case RENDERPATH_SOFT:
5642                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5643                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5644                         break;
5645                 case RENDERPATH_GL20:
5646                 case RENDERPATH_GLES2:
5647                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5648                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5649                         break;
5650                 }
5651         }
5652 }
5653
5654 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5655 {
5656         r_viewport_t viewport;
5657
5658         CHECKGLERROR
5659
5660         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5661         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);
5662         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5663         R_SetViewport(&viewport);
5664         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5665         GL_Color(1, 1, 1, 1);
5666         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5667         GL_BlendFunc(GL_ONE, GL_ZERO);
5668         GL_ScissorTest(false);
5669         GL_DepthMask(false);
5670         GL_DepthRange(0, 1);
5671         GL_DepthTest(false);
5672         GL_DepthFunc(GL_LEQUAL);
5673         R_EntityMatrix(&identitymatrix);
5674         R_Mesh_ResetTextureState();
5675         GL_PolygonOffset(0, 0);
5676         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5677         switch(vid.renderpath)
5678         {
5679         case RENDERPATH_GL11:
5680         case RENDERPATH_GL13:
5681         case RENDERPATH_GL20:
5682         case RENDERPATH_GLES1:
5683         case RENDERPATH_GLES2:
5684                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5685                 break;
5686         case RENDERPATH_D3D9:
5687         case RENDERPATH_D3D10:
5688         case RENDERPATH_D3D11:
5689         case RENDERPATH_SOFT:
5690                 break;
5691         }
5692         GL_CullFace(GL_NONE);
5693
5694         CHECKGLERROR
5695 }
5696
5697 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5698 {
5699         DrawQ_Finish();
5700
5701         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5702 }
5703
5704 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5705 {
5706         DrawQ_Finish();
5707
5708         R_SetupView(true, fbo, depthtexture, colortexture);
5709         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5710         GL_Color(1, 1, 1, 1);
5711         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5712         GL_BlendFunc(GL_ONE, GL_ZERO);
5713         GL_ScissorTest(true);
5714         GL_DepthMask(true);
5715         GL_DepthRange(0, 1);
5716         GL_DepthTest(true);
5717         GL_DepthFunc(GL_LEQUAL);
5718         R_EntityMatrix(&identitymatrix);
5719         R_Mesh_ResetTextureState();
5720         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5721         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5722         switch(vid.renderpath)
5723         {
5724         case RENDERPATH_GL11:
5725         case RENDERPATH_GL13:
5726         case RENDERPATH_GL20:
5727         case RENDERPATH_GLES1:
5728         case RENDERPATH_GLES2:
5729                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5730                 break;
5731         case RENDERPATH_D3D9:
5732         case RENDERPATH_D3D10:
5733         case RENDERPATH_D3D11:
5734         case RENDERPATH_SOFT:
5735                 break;
5736         }
5737         GL_CullFace(r_refdef.view.cullface_back);
5738 }
5739
5740 /*
5741 ================
5742 R_RenderView_UpdateViewVectors
5743 ================
5744 */
5745 void R_RenderView_UpdateViewVectors(void)
5746 {
5747         // break apart the view matrix into vectors for various purposes
5748         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5749         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5750         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5751         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5752         // make an inverted copy of the view matrix for tracking sprites
5753         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5754 }
5755
5756 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5757 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5758
5759 static void R_Water_StartFrame(void)
5760 {
5761         int i;
5762         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5763         r_waterstate_waterplane_t *p;
5764         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;
5765
5766         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5767                 return;
5768
5769         switch(vid.renderpath)
5770         {
5771         case RENDERPATH_GL20:
5772         case RENDERPATH_D3D9:
5773         case RENDERPATH_D3D10:
5774         case RENDERPATH_D3D11:
5775         case RENDERPATH_SOFT:
5776         case RENDERPATH_GLES2:
5777                 break;
5778         case RENDERPATH_GL11:
5779         case RENDERPATH_GL13:
5780         case RENDERPATH_GLES1:
5781                 return;
5782         }
5783
5784         // set waterwidth and waterheight to the water resolution that will be
5785         // used (often less than the screen resolution for faster rendering)
5786         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5787
5788         // calculate desired texture sizes
5789         // can't use water if the card does not support the texture size
5790         if (!r_water.integer || r_showsurfaces.integer)
5791                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5792         else if (vid.support.arb_texture_non_power_of_two)
5793         {
5794                 texturewidth = waterwidth;
5795                 textureheight = waterheight;
5796                 camerawidth = waterwidth;
5797                 cameraheight = waterheight;
5798         }
5799         else
5800         {
5801                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5802                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5803                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5804                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5805         }
5806
5807         // allocate textures as needed
5808         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))
5809         {
5810                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5811                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5812                 {
5813                         if (p->texture_refraction)
5814                                 R_FreeTexture(p->texture_refraction);
5815                         p->texture_refraction = NULL;
5816                         if (p->fbo_refraction)
5817                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5818                         p->fbo_refraction = 0;
5819                         if (p->texture_reflection)
5820                                 R_FreeTexture(p->texture_reflection);
5821                         p->texture_reflection = NULL;
5822                         if (p->fbo_reflection)
5823                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5824                         p->fbo_reflection = 0;
5825                         if (p->texture_camera)
5826                                 R_FreeTexture(p->texture_camera);
5827                         p->texture_camera = NULL;
5828                         if (p->fbo_camera)
5829                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5830                         p->fbo_camera = 0;
5831                 }
5832                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5833                 r_fb.water.texturewidth = texturewidth;
5834                 r_fb.water.textureheight = textureheight;
5835                 r_fb.water.camerawidth = camerawidth;
5836                 r_fb.water.cameraheight = cameraheight;
5837         }
5838
5839         if (r_fb.water.texturewidth)
5840         {
5841                 int scaledwidth, scaledheight;
5842
5843                 r_fb.water.enabled = true;
5844
5845                 // water resolution is usually reduced
5846                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5847                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5848                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5849
5850                 // set up variables that will be used in shader setup
5851                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5852                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5853                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5854                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5855         }
5856
5857         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5858         r_fb.water.numwaterplanes = 0;
5859 }
5860
5861 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5862 {
5863         int planeindex, bestplaneindex, vertexindex;
5864         vec3_t mins, maxs, normal, center, v, n;
5865         vec_t planescore, bestplanescore;
5866         mplane_t plane;
5867         r_waterstate_waterplane_t *p;
5868         texture_t *t = R_GetCurrentTexture(surface->texture);
5869
5870         rsurface.texture = t;
5871         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5872         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5873         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5874                 return;
5875         // average the vertex normals, find the surface bounds (after deformvertexes)
5876         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5877         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5878         VectorCopy(n, normal);
5879         VectorCopy(v, mins);
5880         VectorCopy(v, maxs);
5881         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5882         {
5883                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5884                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5885                 VectorAdd(normal, n, normal);
5886                 mins[0] = min(mins[0], v[0]);
5887                 mins[1] = min(mins[1], v[1]);
5888                 mins[2] = min(mins[2], v[2]);
5889                 maxs[0] = max(maxs[0], v[0]);
5890                 maxs[1] = max(maxs[1], v[1]);
5891                 maxs[2] = max(maxs[2], v[2]);
5892         }
5893         VectorNormalize(normal);
5894         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5895
5896         VectorCopy(normal, plane.normal);
5897         VectorNormalize(plane.normal);
5898         plane.dist = DotProduct(center, plane.normal);
5899         PlaneClassify(&plane);
5900         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5901         {
5902                 // skip backfaces (except if nocullface is set)
5903 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5904 //                      return;
5905                 VectorNegate(plane.normal, plane.normal);
5906                 plane.dist *= -1;
5907                 PlaneClassify(&plane);
5908         }
5909
5910
5911         // find a matching plane if there is one
5912         bestplaneindex = -1;
5913         bestplanescore = 1048576.0f;
5914         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5915         {
5916                 if(p->camera_entity == t->camera_entity)
5917                 {
5918                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5919                         if (bestplaneindex < 0 || bestplanescore > planescore)
5920                         {
5921                                 bestplaneindex = planeindex;
5922                                 bestplanescore = planescore;
5923                         }
5924                 }
5925         }
5926         planeindex = bestplaneindex;
5927         p = r_fb.water.waterplanes + planeindex;
5928
5929         // if this surface does not fit any known plane rendered this frame, add one
5930         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5931         {
5932                 // store the new plane
5933                 planeindex = r_fb.water.numwaterplanes++;
5934                 p = r_fb.water.waterplanes + planeindex;
5935                 p->plane = plane;
5936                 // clear materialflags and pvs
5937                 p->materialflags = 0;
5938                 p->pvsvalid = false;
5939                 p->camera_entity = t->camera_entity;
5940                 VectorCopy(mins, p->mins);
5941                 VectorCopy(maxs, p->maxs);
5942         }
5943         else
5944         {
5945                 // merge mins/maxs when we're adding this surface to the plane
5946                 p->mins[0] = min(p->mins[0], mins[0]);
5947                 p->mins[1] = min(p->mins[1], mins[1]);
5948                 p->mins[2] = min(p->mins[2], mins[2]);
5949                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5950                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5951                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5952         }
5953         // merge this surface's materialflags into the waterplane
5954         p->materialflags |= t->currentmaterialflags;
5955         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5956         {
5957                 // merge this surface's PVS into the waterplane
5958                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5959                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5960                 {
5961                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5962                         p->pvsvalid = true;
5963                 }
5964         }
5965 }
5966
5967 extern cvar_t r_drawparticles;
5968 extern cvar_t r_drawdecals;
5969
5970 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5971 {
5972         int myscissor[4];
5973         r_refdef_view_t originalview;
5974         r_refdef_view_t myview;
5975         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;
5976         r_waterstate_waterplane_t *p;
5977         vec3_t visorigin;
5978         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;
5979         char vabuf[1024];
5980
5981         originalview = r_refdef.view;
5982
5983         // lowquality hack, temporarily shut down some cvars and restore afterwards
5984         qualityreduction = r_water_lowquality.integer;
5985         if (qualityreduction > 0)
5986         {
5987                 if (qualityreduction >= 1)
5988                 {
5989                         old_r_shadows = r_shadows.integer;
5990                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5991                         old_r_dlight = r_shadow_realtime_dlight.integer;
5992                         Cvar_SetValueQuick(&r_shadows, 0);
5993                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5994                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5995                 }
5996                 if (qualityreduction >= 2)
5997                 {
5998                         old_r_dynamic = r_dynamic.integer;
5999                         old_r_particles = r_drawparticles.integer;
6000                         old_r_decals = r_drawdecals.integer;
6001                         Cvar_SetValueQuick(&r_dynamic, 0);
6002                         Cvar_SetValueQuick(&r_drawparticles, 0);
6003                         Cvar_SetValueQuick(&r_drawdecals, 0);
6004                 }
6005         }
6006
6007         // make sure enough textures are allocated
6008         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6009         {
6010                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6011                 {
6012                         if (!p->texture_refraction)
6013                                 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);
6014                         if (!p->texture_refraction)
6015                                 goto error;
6016                         if (usewaterfbo)
6017                         {
6018                                 if (r_fb.water.depthtexture == NULL)
6019                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6020                                 if (p->fbo_refraction == 0)
6021                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6022                         }
6023                 }
6024                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6025                 {
6026                         if (!p->texture_camera)
6027                                 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);
6028                         if (!p->texture_camera)
6029                                 goto error;
6030                         if (usewaterfbo)
6031                         {
6032                                 if (r_fb.water.depthtexture == NULL)
6033                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6034                                 if (p->fbo_camera == 0)
6035                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6036                         }
6037                 }
6038
6039                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6040                 {
6041                         if (!p->texture_reflection)
6042                                 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);
6043                         if (!p->texture_reflection)
6044                                 goto error;
6045                         if (usewaterfbo)
6046                         {
6047                                 if (r_fb.water.depthtexture == NULL)
6048                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6049                                 if (p->fbo_reflection == 0)
6050                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6051                         }
6052                 }
6053         }
6054
6055         // render views
6056         r_refdef.view = originalview;
6057         r_refdef.view.showdebug = false;
6058         r_refdef.view.width = r_fb.water.waterwidth;
6059         r_refdef.view.height = r_fb.water.waterheight;
6060         r_refdef.view.useclipplane = true;
6061         myview = r_refdef.view;
6062         r_fb.water.renderingscene = true;
6063         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6064         {
6065                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6066                 {
6067                         r_refdef.view = myview;
6068                         if(r_water_scissormode.integer)
6069                         {
6070                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6071                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6072                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6073                         }
6074
6075                         // render reflected scene and copy into texture
6076                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6077                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6078                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6079                         r_refdef.view.clipplane = p->plane;
6080                         // reverse the cullface settings for this render
6081                         r_refdef.view.cullface_front = GL_FRONT;
6082                         r_refdef.view.cullface_back = GL_BACK;
6083                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6084                         {
6085                                 r_refdef.view.usecustompvs = true;
6086                                 if (p->pvsvalid)
6087                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6088                                 else
6089                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6090                         }
6091
6092                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6093                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6094                         R_ClearScreen(r_refdef.fogenabled);
6095                         if(r_water_scissormode.integer & 2)
6096                                 R_View_UpdateWithScissor(myscissor);
6097                         else
6098                                 R_View_Update();
6099                         R_AnimCache_CacheVisibleEntities();
6100                         if(r_water_scissormode.integer & 1)
6101                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6102                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6103
6104                         if (!p->fbo_reflection)
6105                                 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);
6106                         r_fb.water.hideplayer = false;
6107                 }
6108
6109                 // render the normal view scene and copy into texture
6110                 // (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)
6111                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6112                 {
6113                         r_refdef.view = myview;
6114                         if(r_water_scissormode.integer)
6115                         {
6116                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6117                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6118                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6119                         }
6120
6121                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6122
6123                         r_refdef.view.clipplane = p->plane;
6124                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6125                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6126
6127                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6128                         {
6129                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6130                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6131                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6132                                 R_RenderView_UpdateViewVectors();
6133                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6134                                 {
6135                                         r_refdef.view.usecustompvs = true;
6136                                         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);
6137                                 }
6138                         }
6139
6140                         PlaneClassify(&r_refdef.view.clipplane);
6141
6142                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6143                         R_ClearScreen(r_refdef.fogenabled);
6144                         if(r_water_scissormode.integer & 2)
6145                                 R_View_UpdateWithScissor(myscissor);
6146                         else
6147                                 R_View_Update();
6148                         R_AnimCache_CacheVisibleEntities();
6149                         if(r_water_scissormode.integer & 1)
6150                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6151                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6152
6153                         if (!p->fbo_refraction)
6154                                 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);
6155                         r_fb.water.hideplayer = false;
6156                 }
6157                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6158                 {
6159                         r_refdef.view = myview;
6160
6161                         r_refdef.view.clipplane = p->plane;
6162                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6163                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6164
6165                         r_refdef.view.width = r_fb.water.camerawidth;
6166                         r_refdef.view.height = r_fb.water.cameraheight;
6167                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6168                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6169                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6170                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6171
6172                         if(p->camera_entity)
6173                         {
6174                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6175                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6176                         }
6177
6178                         // note: all of the view is used for displaying... so
6179                         // there is no use in scissoring
6180
6181                         // reverse the cullface settings for this render
6182                         r_refdef.view.cullface_front = GL_FRONT;
6183                         r_refdef.view.cullface_back = GL_BACK;
6184                         // also reverse the view matrix
6185                         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
6186                         R_RenderView_UpdateViewVectors();
6187                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6188                         {
6189                                 r_refdef.view.usecustompvs = true;
6190                                 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);
6191                         }
6192                         
6193                         // camera needs no clipplane
6194                         r_refdef.view.useclipplane = false;
6195
6196                         PlaneClassify(&r_refdef.view.clipplane);
6197
6198                         r_fb.water.hideplayer = false;
6199
6200                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6201                         R_ClearScreen(r_refdef.fogenabled);
6202                         R_View_Update();
6203                         R_AnimCache_CacheVisibleEntities();
6204                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6205
6206                         if (!p->fbo_camera)
6207                                 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);
6208                         r_fb.water.hideplayer = false;
6209                 }
6210
6211         }
6212         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6213         r_fb.water.renderingscene = false;
6214         r_refdef.view = originalview;
6215         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6216         if (!r_fb.water.depthtexture)
6217                 R_ClearScreen(r_refdef.fogenabled);
6218         R_View_Update();
6219         R_AnimCache_CacheVisibleEntities();
6220         goto finish;
6221 error:
6222         r_refdef.view = originalview;
6223         r_fb.water.renderingscene = false;
6224         Cvar_SetValueQuick(&r_water, 0);
6225         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6226 finish:
6227         // lowquality hack, restore cvars
6228         if (qualityreduction > 0)
6229         {
6230                 if (qualityreduction >= 1)
6231                 {
6232                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6233                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6234                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6235                 }
6236                 if (qualityreduction >= 2)
6237                 {
6238                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6239                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6240                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6241                 }
6242         }
6243 }
6244
6245 static void R_Bloom_StartFrame(void)
6246 {
6247         int i;
6248         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6249         int viewwidth, viewheight;
6250         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6251         textype_t textype = TEXTYPE_COLORBUFFER;
6252
6253         switch (vid.renderpath)
6254         {
6255         case RENDERPATH_GL20:
6256                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6257                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6258                 {
6259                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6260                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6261                 }
6262                 break;
6263         case RENDERPATH_GL11:
6264         case RENDERPATH_GL13:
6265         case RENDERPATH_GLES1:
6266         case RENDERPATH_GLES2:
6267         case RENDERPATH_D3D9:
6268         case RENDERPATH_D3D10:
6269         case RENDERPATH_D3D11:
6270                 r_fb.usedepthtextures = false;
6271                 break;
6272         case RENDERPATH_SOFT:
6273                 r_fb.usedepthtextures = true;
6274                 break;
6275         }
6276
6277         if (r_viewscale_fpsscaling.integer)
6278         {
6279                 double actualframetime;
6280                 double targetframetime;
6281                 double adjust;
6282                 actualframetime = r_refdef.lastdrawscreentime;
6283                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6284                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6285                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6286                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6287                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6288                 viewscalefpsadjusted += adjust;
6289                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6290         }
6291         else
6292                 viewscalefpsadjusted = 1.0f;
6293
6294         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6295
6296         switch(vid.renderpath)
6297         {
6298         case RENDERPATH_GL20:
6299         case RENDERPATH_D3D9:
6300         case RENDERPATH_D3D10:
6301         case RENDERPATH_D3D11:
6302         case RENDERPATH_SOFT:
6303         case RENDERPATH_GLES2:
6304                 break;
6305         case RENDERPATH_GL11:
6306         case RENDERPATH_GL13:
6307         case RENDERPATH_GLES1:
6308                 return;
6309         }
6310
6311         // set bloomwidth and bloomheight to the bloom resolution that will be
6312         // used (often less than the screen resolution for faster rendering)
6313         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6314         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6315         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6316         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6317         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6318
6319         // calculate desired texture sizes
6320         if (vid.support.arb_texture_non_power_of_two)
6321         {
6322                 screentexturewidth = vid.width;
6323                 screentextureheight = vid.height;
6324                 bloomtexturewidth = r_fb.bloomwidth;
6325                 bloomtextureheight = r_fb.bloomheight;
6326         }
6327         else
6328         {
6329                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6330                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6331                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6332                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6333         }
6334
6335         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))
6336         {
6337                 Cvar_SetValueQuick(&r_bloom, 0);
6338                 Cvar_SetValueQuick(&r_motionblur, 0);
6339                 Cvar_SetValueQuick(&r_damageblur, 0);
6340         }
6341
6342         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6343          && !r_bloom.integer
6344          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6345          && !useviewfbo
6346          && r_viewscale.value == 1.0f
6347          && !r_viewscale_fpsscaling.integer)
6348                 screentexturewidth = screentextureheight = 0;
6349         if (!r_bloom.integer)
6350                 bloomtexturewidth = bloomtextureheight = 0;
6351
6352         // allocate textures as needed
6353         if (r_fb.screentexturewidth != screentexturewidth
6354          || r_fb.screentextureheight != screentextureheight
6355          || r_fb.bloomtexturewidth != bloomtexturewidth
6356          || r_fb.bloomtextureheight != bloomtextureheight
6357          || r_fb.textype != textype
6358          || useviewfbo != (r_fb.fbo != 0))
6359         {
6360                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6361                 {
6362                         if (r_fb.bloomtexture[i])
6363                                 R_FreeTexture(r_fb.bloomtexture[i]);
6364                         r_fb.bloomtexture[i] = NULL;
6365
6366                         if (r_fb.bloomfbo[i])
6367                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6368                         r_fb.bloomfbo[i] = 0;
6369                 }
6370
6371                 if (r_fb.fbo)
6372                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6373                 r_fb.fbo = 0;
6374
6375                 if (r_fb.colortexture)
6376                         R_FreeTexture(r_fb.colortexture);
6377                 r_fb.colortexture = NULL;
6378
6379                 if (r_fb.depthtexture)
6380                         R_FreeTexture(r_fb.depthtexture);
6381                 r_fb.depthtexture = NULL;
6382
6383                 if (r_fb.ghosttexture)
6384                         R_FreeTexture(r_fb.ghosttexture);
6385                 r_fb.ghosttexture = NULL;
6386
6387                 r_fb.screentexturewidth = screentexturewidth;
6388                 r_fb.screentextureheight = screentextureheight;
6389                 r_fb.bloomtexturewidth = bloomtexturewidth;
6390                 r_fb.bloomtextureheight = bloomtextureheight;
6391                 r_fb.textype = textype;
6392
6393                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6394                 {
6395                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6396                                 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);
6397                         r_fb.ghosttexture_valid = false;
6398                         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);
6399                         if (useviewfbo)
6400                         {
6401                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6402                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6403                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6404                         }
6405                 }
6406
6407                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6408                 {
6409                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6410                         {
6411                                 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);
6412                                 if (useviewfbo)
6413                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6414                         }
6415                 }
6416         }
6417
6418         // bloom texture is a different resolution
6419         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6420         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6421         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6422         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6423         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6424
6425         // set up a texcoord array for the full resolution screen image
6426         // (we have to keep this around to copy back during final render)
6427         r_fb.screentexcoord2f[0] = 0;
6428         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6429         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6430         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6431         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6432         r_fb.screentexcoord2f[5] = 0;
6433         r_fb.screentexcoord2f[6] = 0;
6434         r_fb.screentexcoord2f[7] = 0;
6435
6436         if(r_fb.fbo) 
6437         {
6438                 for (i = 1;i < 8;i += 2)
6439                 {
6440                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6441                 }
6442         }
6443
6444         // set up a texcoord array for the reduced resolution bloom image
6445         // (which will be additive blended over the screen image)
6446         r_fb.bloomtexcoord2f[0] = 0;
6447         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6448         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6449         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6450         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6451         r_fb.bloomtexcoord2f[5] = 0;
6452         r_fb.bloomtexcoord2f[6] = 0;
6453         r_fb.bloomtexcoord2f[7] = 0;
6454
6455         switch(vid.renderpath)
6456         {
6457         case RENDERPATH_GL11:
6458         case RENDERPATH_GL13:
6459         case RENDERPATH_GL20:
6460         case RENDERPATH_SOFT:
6461         case RENDERPATH_GLES1:
6462         case RENDERPATH_GLES2:
6463                 break;
6464         case RENDERPATH_D3D9:
6465         case RENDERPATH_D3D10:
6466         case RENDERPATH_D3D11:
6467                 for (i = 0;i < 4;i++)
6468                 {
6469                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6470                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6471                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6472                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6473                 }
6474                 break;
6475         }
6476
6477         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6478
6479         if (r_fb.fbo)
6480                 r_refdef.view.clear = true;
6481 }
6482
6483 static void R_Bloom_MakeTexture(void)
6484 {
6485         int x, range, dir;
6486         float xoffset, yoffset, r, brighten;
6487         rtexture_t *intex;
6488         float colorscale = r_bloom_colorscale.value;
6489
6490         r_refdef.stats[r_stat_bloom]++;
6491     
6492 #if 0
6493     // this copy is unnecessary since it happens in R_BlendView already
6494         if (!r_fb.fbo)
6495         {
6496                 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);
6497                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6498         }
6499 #endif
6500
6501         // scale down screen texture to the bloom texture size
6502         CHECKGLERROR
6503         r_fb.bloomindex = 0;
6504         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6505         R_SetViewport(&r_fb.bloomviewport);
6506         GL_DepthTest(false);
6507         GL_BlendFunc(GL_ONE, GL_ZERO);
6508         GL_Color(colorscale, colorscale, colorscale, 1);
6509         // 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...
6510         switch(vid.renderpath)
6511         {
6512         case RENDERPATH_GL11:
6513         case RENDERPATH_GL13:
6514         case RENDERPATH_GL20:
6515         case RENDERPATH_GLES1:
6516         case RENDERPATH_GLES2:
6517         case RENDERPATH_SOFT:
6518                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6519                 break;
6520         case RENDERPATH_D3D9:
6521         case RENDERPATH_D3D10:
6522         case RENDERPATH_D3D11:
6523                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6524                 break;
6525         }
6526         // TODO: do boxfilter scale-down in shader?
6527         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6528         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6529         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6530
6531         // we now have a properly scaled bloom image
6532         if (!r_fb.bloomfbo[r_fb.bloomindex])
6533         {
6534                 // copy it into the bloom texture
6535                 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);
6536                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6537         }
6538
6539         // multiply bloom image by itself as many times as desired
6540         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6541         {
6542                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6543                 r_fb.bloomindex ^= 1;
6544                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6545                 x *= 2;
6546                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6547                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6548                 {
6549                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6550                         GL_Color(r,r,r,1); // apply fix factor
6551                 }
6552                 else
6553                 {
6554                         if(x <= 2)
6555                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6556                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6557                         GL_Color(1,1,1,1); // no fix factor supported here
6558                 }
6559                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6560                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6561                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6562                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6563
6564                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6565                 {
6566                         // copy the darkened image to a texture
6567                         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);
6568                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6569                 }
6570         }
6571
6572         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6573         brighten = r_bloom_brighten.value;
6574         brighten = sqrt(brighten);
6575         if(range >= 1)
6576                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6577
6578         for (dir = 0;dir < 2;dir++)
6579         {
6580                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6581                 r_fb.bloomindex ^= 1;
6582                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6583                 // blend on at multiple vertical offsets to achieve a vertical blur
6584                 // TODO: do offset blends using GLSL
6585                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6586                 GL_BlendFunc(GL_ONE, GL_ZERO);
6587                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6588                 for (x = -range;x <= range;x++)
6589                 {
6590                         if (!dir){xoffset = 0;yoffset = x;}
6591                         else {xoffset = x;yoffset = 0;}
6592                         xoffset /= (float)r_fb.bloomtexturewidth;
6593                         yoffset /= (float)r_fb.bloomtextureheight;
6594                         // compute a texcoord array with the specified x and y offset
6595                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6596                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6597                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6598                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6599                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6600                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6601                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6602                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6603                         // this r value looks like a 'dot' particle, fading sharply to
6604                         // black at the edges
6605                         // (probably not realistic but looks good enough)
6606                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6607                         //r = brighten/(range*2+1);
6608                         r = brighten / (range * 2 + 1);
6609                         if(range >= 1)
6610                                 r *= (1 - x*x/(float)(range*range));
6611                         GL_Color(r, r, r, 1);
6612                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6613                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6614                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6615                         GL_BlendFunc(GL_ONE, GL_ONE);
6616                 }
6617
6618                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6619                 {
6620                         // copy the vertically or horizontally blurred bloom view to a texture
6621                         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);
6622                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6623                 }
6624         }
6625 }
6626
6627 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6628 {
6629         unsigned int permutation;
6630         float uservecs[4][4];
6631
6632         R_EntityMatrix(&identitymatrix);
6633
6634         switch (vid.renderpath)
6635         {
6636         case RENDERPATH_GL20:
6637         case RENDERPATH_D3D9:
6638         case RENDERPATH_D3D10:
6639         case RENDERPATH_D3D11:
6640         case RENDERPATH_SOFT:
6641         case RENDERPATH_GLES2:
6642                 permutation =
6643                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6644                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6645                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6646                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6647                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6648
6649                 if (r_fb.colortexture)
6650                 {
6651                         if (!r_fb.fbo)
6652                         {
6653                                 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);
6654                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6655                         }
6656
6657                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6658                         {
6659                                 // declare variables
6660                                 float blur_factor, blur_mouseaccel, blur_velocity;
6661                                 static float blur_average; 
6662                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6663
6664                                 // set a goal for the factoring
6665                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6666                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6667                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6668                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6669                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6670                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6671
6672                                 // from the goal, pick an averaged value between goal and last value
6673                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6674                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6675
6676                                 // enforce minimum amount of blur 
6677                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6678
6679                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6680
6681                                 // calculate values into a standard alpha
6682                                 cl.motionbluralpha = 1 - exp(-
6683                                                 (
6684                                                  (r_motionblur.value * blur_factor / 80)
6685                                                  +
6686                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6687                                                 )
6688                                                 /
6689                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6690                                           );
6691
6692                                 // randomization for the blur value to combat persistent ghosting
6693                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6694                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6695
6696                                 // apply the blur
6697                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6698                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6699                                 {
6700                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6701                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6702                                         switch(vid.renderpath)
6703                                         {
6704                                         case RENDERPATH_GL11:
6705                                         case RENDERPATH_GL13:
6706                                         case RENDERPATH_GL20:
6707                                         case RENDERPATH_GLES1:
6708                                         case RENDERPATH_GLES2:
6709                                         case RENDERPATH_SOFT:
6710                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6711                                                 break;
6712                                         case RENDERPATH_D3D9:
6713                                         case RENDERPATH_D3D10:
6714                                         case RENDERPATH_D3D11:
6715                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6716                                                 break;
6717                                         }
6718                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6719                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6720                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6721                                 }
6722
6723                                 // updates old view angles for next pass
6724                                 VectorCopy(cl.viewangles, blur_oldangles);
6725
6726                                 // copy view into the ghost texture
6727                                 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);
6728                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6729                                 r_fb.ghosttexture_valid = true;
6730                         }
6731                 }
6732                 else
6733                 {
6734                         // no r_fb.colortexture means we're rendering to the real fb
6735                         // we may still have to do view tint...
6736                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6737                         {
6738                                 // apply a color tint to the whole view
6739                                 R_ResetViewRendering2D(0, NULL, NULL);
6740                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6741                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6742                                 R_SetupShader_Generic_NoTexture(false, true);
6743                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6744                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6745                         }
6746                         break; // no screen processing, no bloom, skip it
6747                 }
6748
6749                 if (r_fb.bloomtexture[0])
6750                 {
6751                         // make the bloom texture
6752                         R_Bloom_MakeTexture();
6753                 }
6754
6755 #if _MSC_VER >= 1400
6756 #define sscanf sscanf_s
6757 #endif
6758                 memset(uservecs, 0, sizeof(uservecs));
6759                 if (r_glsl_postprocess_uservec1_enable.integer)
6760                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6761                 if (r_glsl_postprocess_uservec2_enable.integer)
6762                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6763                 if (r_glsl_postprocess_uservec3_enable.integer)
6764                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6765                 if (r_glsl_postprocess_uservec4_enable.integer)
6766                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6767
6768                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6769                 GL_Color(1, 1, 1, 1);
6770                 GL_BlendFunc(GL_ONE, GL_ZERO);
6771
6772                 switch(vid.renderpath)
6773                 {
6774                 case RENDERPATH_GL20:
6775                 case RENDERPATH_GLES2:
6776                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6777                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6778                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6779                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6780                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6781                         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]);
6782                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6783                         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]);
6784                         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]);
6785                         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]);
6786                         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]);
6787                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6788                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6789                         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);
6790                         break;
6791                 case RENDERPATH_D3D9:
6792 #ifdef SUPPORTD3D
6793                         // 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...
6794                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6795                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6796                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6797                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6798                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6799                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6800                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6801                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6802                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6803                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6804                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6805                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6806                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6807                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6808 #endif
6809                         break;
6810                 case RENDERPATH_D3D10:
6811                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6812                         break;
6813                 case RENDERPATH_D3D11:
6814                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6815                         break;
6816                 case RENDERPATH_SOFT:
6817                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6818                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6819                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6820                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6821                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6822                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6823                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6824                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6825                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6826                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6827                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6828                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6829                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6830                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6831                         break;
6832                 default:
6833                         break;
6834                 }
6835                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6836                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6837                 break;
6838         case RENDERPATH_GL11:
6839         case RENDERPATH_GL13:
6840         case RENDERPATH_GLES1:
6841                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6842                 {
6843                         // apply a color tint to the whole view
6844                         R_ResetViewRendering2D(0, NULL, NULL);
6845                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6846                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6847                         R_SetupShader_Generic_NoTexture(false, true);
6848                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6849                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6850                 }
6851                 break;
6852         }
6853 }
6854
6855 matrix4x4_t r_waterscrollmatrix;
6856
6857 void R_UpdateFog(void)
6858 {
6859         // Nehahra fog
6860         if (gamemode == GAME_NEHAHRA)
6861         {
6862                 if (gl_fogenable.integer)
6863                 {
6864                         r_refdef.oldgl_fogenable = true;
6865                         r_refdef.fog_density = gl_fogdensity.value;
6866                         r_refdef.fog_red = gl_fogred.value;
6867                         r_refdef.fog_green = gl_foggreen.value;
6868                         r_refdef.fog_blue = gl_fogblue.value;
6869                         r_refdef.fog_alpha = 1;
6870                         r_refdef.fog_start = 0;
6871                         r_refdef.fog_end = gl_skyclip.value;
6872                         r_refdef.fog_height = 1<<30;
6873                         r_refdef.fog_fadedepth = 128;
6874                 }
6875                 else if (r_refdef.oldgl_fogenable)
6876                 {
6877                         r_refdef.oldgl_fogenable = false;
6878                         r_refdef.fog_density = 0;
6879                         r_refdef.fog_red = 0;
6880                         r_refdef.fog_green = 0;
6881                         r_refdef.fog_blue = 0;
6882                         r_refdef.fog_alpha = 0;
6883                         r_refdef.fog_start = 0;
6884                         r_refdef.fog_end = 0;
6885                         r_refdef.fog_height = 1<<30;
6886                         r_refdef.fog_fadedepth = 128;
6887                 }
6888         }
6889
6890         // fog parms
6891         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6892         r_refdef.fog_start = max(0, r_refdef.fog_start);
6893         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6894
6895         if (r_refdef.fog_density && r_drawfog.integer)
6896         {
6897                 r_refdef.fogenabled = true;
6898                 // this is the point where the fog reaches 0.9986 alpha, which we
6899                 // consider a good enough cutoff point for the texture
6900                 // (0.9986 * 256 == 255.6)
6901                 if (r_fog_exp2.integer)
6902                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6903                 else
6904                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6905                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6906                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6907                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6908                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6909                         R_BuildFogHeightTexture();
6910                 // fog color was already set
6911                 // update the fog texture
6912                 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)
6913                         R_BuildFogTexture();
6914                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6915                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6916         }
6917         else
6918                 r_refdef.fogenabled = false;
6919
6920         // fog color
6921         if (r_refdef.fog_density)
6922         {
6923                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6924                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6925                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6926
6927                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6928                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6929                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6930                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6931
6932                 {
6933                         vec3_t fogvec;
6934                         VectorCopy(r_refdef.fogcolor, fogvec);
6935                         //   color.rgb *= ContrastBoost * SceneBrightness;
6936                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6937                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6938                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6939                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6940                 }
6941         }
6942 }
6943
6944 void R_UpdateVariables(void)
6945 {
6946         R_Textures_Frame();
6947
6948         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6949
6950         r_refdef.farclip = r_farclip_base.value;
6951         if (r_refdef.scene.worldmodel)
6952                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6953         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6954
6955         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6956                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6957         r_refdef.polygonfactor = 0;
6958         r_refdef.polygonoffset = 0;
6959         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6960         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6961
6962         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6963         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6964         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6965         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6966         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6967         if (FAKELIGHT_ENABLED)
6968         {
6969                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6970         }
6971         else if (r_refdef.scene.worldmodel)
6972         {
6973                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6974         }
6975         if (r_showsurfaces.integer)
6976         {
6977                 r_refdef.scene.rtworld = false;
6978                 r_refdef.scene.rtworldshadows = false;
6979                 r_refdef.scene.rtdlight = false;
6980                 r_refdef.scene.rtdlightshadows = false;
6981                 r_refdef.lightmapintensity = 0;
6982         }
6983
6984         r_gpuskeletal = false;
6985         switch(vid.renderpath)
6986         {
6987         case RENDERPATH_GL20:
6988                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6989         case RENDERPATH_D3D9:
6990         case RENDERPATH_D3D10:
6991         case RENDERPATH_D3D11:
6992         case RENDERPATH_SOFT:
6993         case RENDERPATH_GLES2:
6994                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6995                 {
6996                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6997                         {
6998                                 // build GLSL gamma texture
6999 #define RAMPWIDTH 256
7000                                 unsigned short ramp[RAMPWIDTH * 3];
7001                                 unsigned char rampbgr[RAMPWIDTH][4];
7002                                 int i;
7003
7004                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7005
7006                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7007                                 for(i = 0; i < RAMPWIDTH; ++i)
7008                                 {
7009                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7010                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7011                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7012                                         rampbgr[i][3] = 0;
7013                                 }
7014                                 if (r_texture_gammaramps)
7015                                 {
7016                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7017                                 }
7018                                 else
7019                                 {
7020                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7021                                 }
7022                         }
7023                 }
7024                 else
7025                 {
7026                         // remove GLSL gamma texture
7027                 }
7028                 break;
7029         case RENDERPATH_GL11:
7030         case RENDERPATH_GL13:
7031         case RENDERPATH_GLES1:
7032                 break;
7033         }
7034 }
7035
7036 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7037 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7038 /*
7039 ================
7040 R_SelectScene
7041 ================
7042 */
7043 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7044         if( scenetype != r_currentscenetype ) {
7045                 // store the old scenetype
7046                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7047                 r_currentscenetype = scenetype;
7048                 // move in the new scene
7049                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7050         }
7051 }
7052
7053 /*
7054 ================
7055 R_GetScenePointer
7056 ================
7057 */
7058 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7059 {
7060         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7061         if( scenetype == r_currentscenetype ) {
7062                 return &r_refdef.scene;
7063         } else {
7064                 return &r_scenes_store[ scenetype ];
7065         }
7066 }
7067
7068 static int R_SortEntities_Compare(const void *ap, const void *bp)
7069 {
7070         const entity_render_t *a = *(const entity_render_t **)ap;
7071         const entity_render_t *b = *(const entity_render_t **)bp;
7072
7073         // 1. compare model
7074         if(a->model < b->model)
7075                 return -1;
7076         if(a->model > b->model)
7077                 return +1;
7078
7079         // 2. compare skin
7080         // TODO possibly calculate the REAL skinnum here first using
7081         // skinscenes?
7082         if(a->skinnum < b->skinnum)
7083                 return -1;
7084         if(a->skinnum > b->skinnum)
7085                 return +1;
7086
7087         // everything we compared is equal
7088         return 0;
7089 }
7090 static void R_SortEntities(void)
7091 {
7092         // below or equal 2 ents, sorting never gains anything
7093         if(r_refdef.scene.numentities <= 2)
7094                 return;
7095         // sort
7096         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7097 }
7098
7099 /*
7100 ================
7101 R_RenderView
7102 ================
7103 */
7104 int dpsoftrast_test;
7105 extern cvar_t r_shadow_bouncegrid;
7106 void R_RenderView(void)
7107 {
7108         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7109         int fbo;
7110         rtexture_t *depthtexture;
7111         rtexture_t *colortexture;
7112
7113         dpsoftrast_test = r_test.integer;
7114
7115         if (r_timereport_active)
7116                 R_TimeReport("start");
7117         r_textureframe++; // used only by R_GetCurrentTexture
7118         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7119
7120         if(R_CompileShader_CheckStaticParms())
7121                 R_GLSL_Restart_f();
7122
7123         if (!r_drawentities.integer)
7124                 r_refdef.scene.numentities = 0;
7125         else if (r_sortentities.integer)
7126                 R_SortEntities();
7127
7128         R_AnimCache_ClearCache();
7129
7130         /* adjust for stereo display */
7131         if(R_Stereo_Active())
7132         {
7133                 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);
7134                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7135         }
7136
7137         if (r_refdef.view.isoverlay)
7138         {
7139                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7140                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7141                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7142                 R_TimeReport("depthclear");
7143
7144                 r_refdef.view.showdebug = false;
7145
7146                 r_fb.water.enabled = false;
7147                 r_fb.water.numwaterplanes = 0;
7148
7149                 R_RenderScene(0, NULL, NULL);
7150
7151                 r_refdef.view.matrix = originalmatrix;
7152
7153                 CHECKGLERROR
7154                 return;
7155         }
7156
7157         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7158         {
7159                 r_refdef.view.matrix = originalmatrix;
7160                 return;
7161         }
7162
7163         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7164
7165         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7166                 // in sRGB fallback, behave similar to true sRGB: convert this
7167                 // value from linear to sRGB
7168                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7169
7170         R_RenderView_UpdateViewVectors();
7171
7172         R_Shadow_UpdateWorldLightSelection();
7173
7174         R_Bloom_StartFrame();
7175
7176         // apply bloom brightness offset
7177         if(r_fb.bloomtexture[0])
7178                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7179
7180         R_Water_StartFrame();
7181
7182         // now we probably have an fbo to render into
7183         fbo = r_fb.fbo;
7184         depthtexture = r_fb.depthtexture;
7185         colortexture = r_fb.colortexture;
7186
7187         CHECKGLERROR
7188         if (r_timereport_active)
7189                 R_TimeReport("viewsetup");
7190
7191         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7192
7193         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7194         {
7195                 R_ClearScreen(r_refdef.fogenabled);
7196                 if (r_timereport_active)
7197                         R_TimeReport("viewclear");
7198         }
7199         r_refdef.view.clear = true;
7200
7201         r_refdef.view.showdebug = true;
7202
7203         R_View_Update();
7204         if (r_timereport_active)
7205                 R_TimeReport("visibility");
7206
7207         R_AnimCache_CacheVisibleEntities();
7208         if (r_timereport_active)
7209                 R_TimeReport("animcache");
7210
7211         R_Shadow_UpdateBounceGridTexture();
7212         if (r_timereport_active && r_shadow_bouncegrid.integer)
7213                 R_TimeReport("bouncegrid");
7214
7215         r_fb.water.numwaterplanes = 0;
7216         if (r_fb.water.enabled)
7217                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7218
7219         R_RenderScene(fbo, depthtexture, colortexture);
7220         r_fb.water.numwaterplanes = 0;
7221
7222         R_BlendView(fbo, depthtexture, colortexture);
7223         if (r_timereport_active)
7224                 R_TimeReport("blendview");
7225
7226         GL_Scissor(0, 0, vid.width, vid.height);
7227         GL_ScissorTest(false);
7228
7229         r_refdef.view.matrix = originalmatrix;
7230
7231         CHECKGLERROR
7232 }
7233
7234 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7235 {
7236         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7237         {
7238                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7239                 if (r_timereport_active)
7240                         R_TimeReport("waterworld");
7241         }
7242
7243         // don't let sound skip if going slow
7244         if (r_refdef.scene.extraupdate)
7245                 S_ExtraUpdate ();
7246
7247         R_DrawModelsAddWaterPlanes();
7248         if (r_timereport_active)
7249                 R_TimeReport("watermodels");
7250
7251         if (r_fb.water.numwaterplanes)
7252         {
7253                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7254                 if (r_timereport_active)
7255                         R_TimeReport("waterscenes");
7256         }
7257 }
7258
7259 extern cvar_t cl_locs_show;
7260 static void R_DrawLocs(void);
7261 static void R_DrawEntityBBoxes(void);
7262 static void R_DrawModelDecals(void);
7263 extern cvar_t cl_decals_newsystem;
7264 extern qboolean r_shadow_usingdeferredprepass;
7265 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7266 {
7267         qboolean shadowmapping = false;
7268
7269         if (r_timereport_active)
7270                 R_TimeReport("beginscene");
7271
7272         r_refdef.stats[r_stat_renders]++;
7273
7274         R_UpdateFog();
7275
7276         // don't let sound skip if going slow
7277         if (r_refdef.scene.extraupdate)
7278                 S_ExtraUpdate ();
7279
7280         R_MeshQueue_BeginScene();
7281
7282         R_SkyStartFrame();
7283
7284         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);
7285
7286         if (r_timereport_active)
7287                 R_TimeReport("skystartframe");
7288
7289         if (cl.csqc_vidvars.drawworld)
7290         {
7291                 // don't let sound skip if going slow
7292                 if (r_refdef.scene.extraupdate)
7293                         S_ExtraUpdate ();
7294
7295                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7296                 {
7297                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7298                         if (r_timereport_active)
7299                                 R_TimeReport("worldsky");
7300                 }
7301
7302                 if (R_DrawBrushModelsSky() && r_timereport_active)
7303                         R_TimeReport("bmodelsky");
7304
7305                 if (skyrendermasked && skyrenderlater)
7306                 {
7307                         // we have to force off the water clipping plane while rendering sky
7308                         R_SetupView(false, fbo, depthtexture, colortexture);
7309                         R_Sky();
7310                         R_SetupView(true, fbo, depthtexture, colortexture);
7311                         if (r_timereport_active)
7312                                 R_TimeReport("sky");
7313                 }
7314         }
7315
7316         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7317         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7318                 R_Shadow_PrepareModelShadows();
7319         if (r_timereport_active)
7320                 R_TimeReport("preparelights");
7321
7322         if (R_Shadow_ShadowMappingEnabled())
7323                 shadowmapping = true;
7324
7325         if (r_shadow_usingdeferredprepass)
7326                 R_Shadow_DrawPrepass();
7327
7328         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7329         {
7330                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7331                 if (r_timereport_active)
7332                         R_TimeReport("worlddepth");
7333         }
7334         if (r_depthfirst.integer >= 2)
7335         {
7336                 R_DrawModelsDepth();
7337                 if (r_timereport_active)
7338                         R_TimeReport("modeldepth");
7339         }
7340
7341         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7342         {
7343                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7344                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7345                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7346                 // don't let sound skip if going slow
7347                 if (r_refdef.scene.extraupdate)
7348                         S_ExtraUpdate ();
7349         }
7350
7351         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7352         {
7353                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7354                 if (r_timereport_active)
7355                         R_TimeReport("world");
7356         }
7357
7358         // don't let sound skip if going slow
7359         if (r_refdef.scene.extraupdate)
7360                 S_ExtraUpdate ();
7361
7362         R_DrawModels();
7363         if (r_timereport_active)
7364                 R_TimeReport("models");
7365
7366         // don't let sound skip if going slow
7367         if (r_refdef.scene.extraupdate)
7368                 S_ExtraUpdate ();
7369
7370         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7371         {
7372                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7373                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7374                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7375                 // don't let sound skip if going slow
7376                 if (r_refdef.scene.extraupdate)
7377                         S_ExtraUpdate ();
7378         }
7379
7380         if (!r_shadow_usingdeferredprepass)
7381         {
7382                 R_Shadow_DrawLights();
7383                 if (r_timereport_active)
7384                         R_TimeReport("rtlights");
7385         }
7386
7387         // don't let sound skip if going slow
7388         if (r_refdef.scene.extraupdate)
7389                 S_ExtraUpdate ();
7390
7391         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7392         {
7393                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7394                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7395                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7396                 // don't let sound skip if going slow
7397                 if (r_refdef.scene.extraupdate)
7398                         S_ExtraUpdate ();
7399         }
7400
7401         if (cl.csqc_vidvars.drawworld)
7402         {
7403                 if (cl_decals_newsystem.integer)
7404                 {
7405                         R_DrawModelDecals();
7406                         if (r_timereport_active)
7407                                 R_TimeReport("modeldecals");
7408                 }
7409                 else
7410                 {
7411                         R_DrawDecals();
7412                         if (r_timereport_active)
7413                                 R_TimeReport("decals");
7414                 }
7415
7416                 R_DrawParticles();
7417                 if (r_timereport_active)
7418                         R_TimeReport("particles");
7419
7420                 R_DrawExplosions();
7421                 if (r_timereport_active)
7422                         R_TimeReport("explosions");
7423
7424                 R_DrawLightningBeams();
7425                 if (r_timereport_active)
7426                         R_TimeReport("lightning");
7427         }
7428
7429         if (cl.csqc_loaded)
7430                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7431
7432         if (r_refdef.view.showdebug)
7433         {
7434                 if (cl_locs_show.integer)
7435                 {
7436                         R_DrawLocs();
7437                         if (r_timereport_active)
7438                                 R_TimeReport("showlocs");
7439                 }
7440
7441                 if (r_drawportals.integer)
7442                 {
7443                         R_DrawPortals();
7444                         if (r_timereport_active)
7445                                 R_TimeReport("portals");
7446                 }
7447
7448                 if (r_showbboxes.value > 0)
7449                 {
7450                         R_DrawEntityBBoxes();
7451                         if (r_timereport_active)
7452                                 R_TimeReport("bboxes");
7453                 }
7454         }
7455
7456         if (r_transparent.integer)
7457         {
7458                 R_MeshQueue_RenderTransparent();
7459                 if (r_timereport_active)
7460                         R_TimeReport("drawtrans");
7461         }
7462
7463         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))
7464         {
7465                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7466                 if (r_timereport_active)
7467                         R_TimeReport("worlddebug");
7468                 R_DrawModelsDebug();
7469                 if (r_timereport_active)
7470                         R_TimeReport("modeldebug");
7471         }
7472
7473         if (cl.csqc_vidvars.drawworld)
7474         {
7475                 R_Shadow_DrawCoronas();
7476                 if (r_timereport_active)
7477                         R_TimeReport("coronas");
7478         }
7479
7480 #if 0
7481         {
7482                 GL_DepthTest(false);
7483                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7484                 GL_Color(1, 1, 1, 1);
7485                 qglBegin(GL_POLYGON);
7486                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7487                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7488                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7489                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7490                 qglEnd();
7491                 qglBegin(GL_POLYGON);
7492                 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]);
7493                 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]);
7494                 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]);
7495                 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]);
7496                 qglEnd();
7497                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7498         }
7499 #endif
7500
7501         // don't let sound skip if going slow
7502         if (r_refdef.scene.extraupdate)
7503                 S_ExtraUpdate ();
7504 }
7505
7506 static const unsigned short bboxelements[36] =
7507 {
7508         5, 1, 3, 5, 3, 7,
7509         6, 2, 0, 6, 0, 4,
7510         7, 3, 2, 7, 2, 6,
7511         4, 0, 1, 4, 1, 5,
7512         4, 5, 7, 4, 7, 6,
7513         1, 0, 2, 1, 2, 3,
7514 };
7515
7516 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7517 {
7518         int i;
7519         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7520
7521         RSurf_ActiveWorldEntity();
7522
7523         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7524         GL_DepthMask(false);
7525         GL_DepthRange(0, 1);
7526         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7527 //      R_Mesh_ResetTextureState();
7528
7529         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7530         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7531         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7532         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7533         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7534         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7535         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7536         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7537         R_FillColors(color4f, 8, cr, cg, cb, ca);
7538         if (r_refdef.fogenabled)
7539         {
7540                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7541                 {
7542                         f1 = RSurf_FogVertex(v);
7543                         f2 = 1 - f1;
7544                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7545                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7546                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7547                 }
7548         }
7549         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7550         R_Mesh_ResetTextureState();
7551         R_SetupShader_Generic_NoTexture(false, false);
7552         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7553 }
7554
7555 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7556 {
7557         prvm_prog_t *prog = SVVM_prog;
7558         int i;
7559         float color[4];
7560         prvm_edict_t *edict;
7561
7562         // this function draws bounding boxes of server entities
7563         if (!sv.active)
7564                 return;
7565
7566         GL_CullFace(GL_NONE);
7567         R_SetupShader_Generic_NoTexture(false, false);
7568
7569         for (i = 0;i < numsurfaces;i++)
7570         {
7571                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7572                 switch ((int)PRVM_serveredictfloat(edict, solid))
7573                 {
7574                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7575                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7576                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7577                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7578                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7579                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7580                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7581                 }
7582                 color[3] *= r_showbboxes.value;
7583                 color[3] = bound(0, color[3], 1);
7584                 GL_DepthTest(!r_showdisabledepthtest.integer);
7585                 GL_CullFace(r_refdef.view.cullface_front);
7586                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7587         }
7588 }
7589
7590 static void R_DrawEntityBBoxes(void)
7591 {
7592         int i;
7593         prvm_edict_t *edict;
7594         vec3_t center;
7595         prvm_prog_t *prog = SVVM_prog;
7596
7597         // this function draws bounding boxes of server entities
7598         if (!sv.active)
7599                 return;
7600
7601         for (i = 0;i < prog->num_edicts;i++)
7602         {
7603                 edict = PRVM_EDICT_NUM(i);
7604                 if (edict->priv.server->free)
7605                         continue;
7606                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7607                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7608                         continue;
7609                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7610                         continue;
7611                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7612                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7613         }
7614 }
7615
7616 static const int nomodelelement3i[24] =
7617 {
7618         5, 2, 0,
7619         5, 1, 2,
7620         5, 0, 3,
7621         5, 3, 1,
7622         0, 2, 4,
7623         2, 1, 4,
7624         3, 0, 4,
7625         1, 3, 4
7626 };
7627
7628 static const unsigned short nomodelelement3s[24] =
7629 {
7630         5, 2, 0,
7631         5, 1, 2,
7632         5, 0, 3,
7633         5, 3, 1,
7634         0, 2, 4,
7635         2, 1, 4,
7636         3, 0, 4,
7637         1, 3, 4
7638 };
7639
7640 static const float nomodelvertex3f[6*3] =
7641 {
7642         -16,   0,   0,
7643          16,   0,   0,
7644           0, -16,   0,
7645           0,  16,   0,
7646           0,   0, -16,
7647           0,   0,  16
7648 };
7649
7650 static const float nomodelcolor4f[6*4] =
7651 {
7652         0.0f, 0.0f, 0.5f, 1.0f,
7653         0.0f, 0.0f, 0.5f, 1.0f,
7654         0.0f, 0.5f, 0.0f, 1.0f,
7655         0.0f, 0.5f, 0.0f, 1.0f,
7656         0.5f, 0.0f, 0.0f, 1.0f,
7657         0.5f, 0.0f, 0.0f, 1.0f
7658 };
7659
7660 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7661 {
7662         int i;
7663         float f1, f2, *c;
7664         float color4f[6*4];
7665
7666         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);
7667
7668         // this is only called once per entity so numsurfaces is always 1, and
7669         // surfacelist is always {0}, so this code does not handle batches
7670
7671         if (rsurface.ent_flags & RENDER_ADDITIVE)
7672         {
7673                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7674                 GL_DepthMask(false);
7675         }
7676         else if (rsurface.colormod[3] < 1)
7677         {
7678                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7679                 GL_DepthMask(false);
7680         }
7681         else
7682         {
7683                 GL_BlendFunc(GL_ONE, GL_ZERO);
7684                 GL_DepthMask(true);
7685         }
7686         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7687         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7688         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7689         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7690         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7691         for (i = 0, c = color4f;i < 6;i++, c += 4)
7692         {
7693                 c[0] *= rsurface.colormod[0];
7694                 c[1] *= rsurface.colormod[1];
7695                 c[2] *= rsurface.colormod[2];
7696                 c[3] *= rsurface.colormod[3];
7697         }
7698         if (r_refdef.fogenabled)
7699         {
7700                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7701                 {
7702                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7703                         f2 = 1 - f1;
7704                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7705                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7706                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7707                 }
7708         }
7709 //      R_Mesh_ResetTextureState();
7710         R_SetupShader_Generic_NoTexture(false, false);
7711         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7712         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7713 }
7714
7715 void R_DrawNoModel(entity_render_t *ent)
7716 {
7717         vec3_t org;
7718         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7719         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7720                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7721         else
7722                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7723 }
7724
7725 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7726 {
7727         vec3_t right1, right2, diff, normal;
7728
7729         VectorSubtract (org2, org1, normal);
7730
7731         // calculate 'right' vector for start
7732         VectorSubtract (r_refdef.view.origin, org1, diff);
7733         CrossProduct (normal, diff, right1);
7734         VectorNormalize (right1);
7735
7736         // calculate 'right' vector for end
7737         VectorSubtract (r_refdef.view.origin, org2, diff);
7738         CrossProduct (normal, diff, right2);
7739         VectorNormalize (right2);
7740
7741         vert[ 0] = org1[0] + width * right1[0];
7742         vert[ 1] = org1[1] + width * right1[1];
7743         vert[ 2] = org1[2] + width * right1[2];
7744         vert[ 3] = org1[0] - width * right1[0];
7745         vert[ 4] = org1[1] - width * right1[1];
7746         vert[ 5] = org1[2] - width * right1[2];
7747         vert[ 6] = org2[0] - width * right2[0];
7748         vert[ 7] = org2[1] - width * right2[1];
7749         vert[ 8] = org2[2] - width * right2[2];
7750         vert[ 9] = org2[0] + width * right2[0];
7751         vert[10] = org2[1] + width * right2[1];
7752         vert[11] = org2[2] + width * right2[2];
7753 }
7754
7755 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)
7756 {
7757         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7758         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7759         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7760         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7761         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7762         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7763         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7764         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7765         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7766         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7767         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7768         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7769 }
7770
7771 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7772 {
7773         int i;
7774         float *vertex3f;
7775         float v[3];
7776         VectorSet(v, x, y, z);
7777         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7778                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7779                         break;
7780         if (i == mesh->numvertices)
7781         {
7782                 if (mesh->numvertices < mesh->maxvertices)
7783                 {
7784                         VectorCopy(v, vertex3f);
7785                         mesh->numvertices++;
7786                 }
7787                 return mesh->numvertices;
7788         }
7789         else
7790                 return i;
7791 }
7792
7793 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7794 {
7795         int i;
7796         int *e, element[3];
7797         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7798         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7799         e = mesh->element3i + mesh->numtriangles * 3;
7800         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7801         {
7802                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7803                 if (mesh->numtriangles < mesh->maxtriangles)
7804                 {
7805                         *e++ = element[0];
7806                         *e++ = element[1];
7807                         *e++ = element[2];
7808                         mesh->numtriangles++;
7809                 }
7810                 element[1] = element[2];
7811         }
7812 }
7813
7814 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7815 {
7816         int i;
7817         int *e, element[3];
7818         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7819         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7820         e = mesh->element3i + mesh->numtriangles * 3;
7821         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7822         {
7823                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7824                 if (mesh->numtriangles < mesh->maxtriangles)
7825                 {
7826                         *e++ = element[0];
7827                         *e++ = element[1];
7828                         *e++ = element[2];
7829                         mesh->numtriangles++;
7830                 }
7831                 element[1] = element[2];
7832         }
7833 }
7834
7835 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7836 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7837 {
7838         int planenum, planenum2;
7839         int w;
7840         int tempnumpoints;
7841         mplane_t *plane, *plane2;
7842         double maxdist;
7843         double temppoints[2][256*3];
7844         // figure out how large a bounding box we need to properly compute this brush
7845         maxdist = 0;
7846         for (w = 0;w < numplanes;w++)
7847                 maxdist = max(maxdist, fabs(planes[w].dist));
7848         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7849         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7850         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7851         {
7852                 w = 0;
7853                 tempnumpoints = 4;
7854                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7855                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7856                 {
7857                         if (planenum2 == planenum)
7858                                 continue;
7859                         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);
7860                         w = !w;
7861                 }
7862                 if (tempnumpoints < 3)
7863                         continue;
7864                 // generate elements forming a triangle fan for this polygon
7865                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7866         }
7867 }
7868
7869 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)
7870 {
7871         texturelayer_t *layer;
7872         layer = t->currentlayers + t->currentnumlayers++;
7873         layer->type = type;
7874         layer->depthmask = depthmask;
7875         layer->blendfunc1 = blendfunc1;
7876         layer->blendfunc2 = blendfunc2;
7877         layer->texture = texture;
7878         layer->texmatrix = *matrix;
7879         layer->color[0] = r;
7880         layer->color[1] = g;
7881         layer->color[2] = b;
7882         layer->color[3] = a;
7883 }
7884
7885 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7886 {
7887         if(parms[0] == 0 && parms[1] == 0)
7888                 return false;
7889         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7890                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7891                         return false;
7892         return true;
7893 }
7894
7895 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7896 {
7897         double index, f;
7898         index = parms[2] + rsurface.shadertime * parms[3];
7899         index -= floor(index);
7900         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7901         {
7902         default:
7903         case Q3WAVEFUNC_NONE:
7904         case Q3WAVEFUNC_NOISE:
7905         case Q3WAVEFUNC_COUNT:
7906                 f = 0;
7907                 break;
7908         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7909         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7910         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7911         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7912         case Q3WAVEFUNC_TRIANGLE:
7913                 index *= 4;
7914                 f = index - floor(index);
7915                 if (index < 1)
7916                 {
7917                         // f = f;
7918                 }
7919                 else if (index < 2)
7920                         f = 1 - f;
7921                 else if (index < 3)
7922                         f = -f;
7923                 else
7924                         f = -(1 - f);
7925                 break;
7926         }
7927         f = parms[0] + parms[1] * f;
7928         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7929                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7930         return (float) f;
7931 }
7932
7933 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7934 {
7935         int w, h, idx;
7936         double f;
7937         double offsetd[2];
7938         float tcmat[12];
7939         matrix4x4_t matrix, temp;
7940         switch(tcmod->tcmod)
7941         {
7942                 case Q3TCMOD_COUNT:
7943                 case Q3TCMOD_NONE:
7944                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7945                                 matrix = r_waterscrollmatrix;
7946                         else
7947                                 matrix = identitymatrix;
7948                         break;
7949                 case Q3TCMOD_ENTITYTRANSLATE:
7950                         // this is used in Q3 to allow the gamecode to control texcoord
7951                         // scrolling on the entity, which is not supported in darkplaces yet.
7952                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7953                         break;
7954                 case Q3TCMOD_ROTATE:
7955                         f = tcmod->parms[0] * rsurface.shadertime;
7956                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7957                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7958                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7959                         break;
7960                 case Q3TCMOD_SCALE:
7961                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7962                         break;
7963                 case Q3TCMOD_SCROLL:
7964                         // extra care is needed because of precision breakdown with large values of time
7965                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7966                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7967                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7968                         break;
7969                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7970                         w = (int) tcmod->parms[0];
7971                         h = (int) tcmod->parms[1];
7972                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7973                         f = f - floor(f);
7974                         idx = (int) floor(f * w * h);
7975                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7976                         break;
7977                 case Q3TCMOD_STRETCH:
7978                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7979                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7980                         break;
7981                 case Q3TCMOD_TRANSFORM:
7982                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7983                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7984                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7985                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7986                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7987                         break;
7988                 case Q3TCMOD_TURBULENT:
7989                         // this is handled in the RSurf_PrepareVertices function
7990                         matrix = identitymatrix;
7991                         break;
7992         }
7993         temp = *texmatrix;
7994         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7995 }
7996
7997 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7998 {
7999         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8000         char name[MAX_QPATH];
8001         skinframe_t *skinframe;
8002         unsigned char pixels[296*194];
8003         strlcpy(cache->name, skinname, sizeof(cache->name));
8004         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8005         if (developer_loading.integer)
8006                 Con_Printf("loading %s\n", name);
8007         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8008         if (!skinframe || !skinframe->base)
8009         {
8010                 unsigned char *f;
8011                 fs_offset_t filesize;
8012                 skinframe = NULL;
8013                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8014                 if (f)
8015                 {
8016                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8017                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8018                         Mem_Free(f);
8019                 }
8020         }
8021         cache->skinframe = skinframe;
8022 }
8023
8024 texture_t *R_GetCurrentTexture(texture_t *t)
8025 {
8026         int i;
8027         const entity_render_t *ent = rsurface.entity;
8028         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8029         q3shaderinfo_layer_tcmod_t *tcmod;
8030
8031         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8032                 return t->currentframe;
8033         t->update_lastrenderframe = r_textureframe;
8034         t->update_lastrenderentity = (void *)ent;
8035
8036         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8037                 t->camera_entity = ent->entitynumber;
8038         else
8039                 t->camera_entity = 0;
8040
8041         // switch to an alternate material if this is a q1bsp animated material
8042         {
8043                 texture_t *texture = t;
8044                 int s = rsurface.ent_skinnum;
8045                 if ((unsigned int)s >= (unsigned int)model->numskins)
8046                         s = 0;
8047                 if (model->skinscenes)
8048                 {
8049                         if (model->skinscenes[s].framecount > 1)
8050                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8051                         else
8052                                 s = model->skinscenes[s].firstframe;
8053                 }
8054                 if (s > 0)
8055                         t = t + s * model->num_surfaces;
8056                 if (t->animated)
8057                 {
8058                         // use an alternate animation if the entity's frame is not 0,
8059                         // and only if the texture has an alternate animation
8060                         if (rsurface.ent_alttextures && t->anim_total[1])
8061                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8062                         else
8063                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8064                 }
8065                 texture->currentframe = t;
8066         }
8067
8068         // update currentskinframe to be a qw skin or animation frame
8069         if (rsurface.ent_qwskin >= 0)
8070         {
8071                 i = rsurface.ent_qwskin;
8072                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8073                 {
8074                         r_qwskincache_size = cl.maxclients;
8075                         if (r_qwskincache)
8076                                 Mem_Free(r_qwskincache);
8077                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8078                 }
8079                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8080                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8081                 t->currentskinframe = r_qwskincache[i].skinframe;
8082                 if (t->currentskinframe == NULL)
8083                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8084         }
8085         else if (t->numskinframes >= 2)
8086                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8087         if (t->backgroundnumskinframes >= 2)
8088                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8089
8090         t->currentmaterialflags = t->basematerialflags;
8091         t->currentalpha = rsurface.colormod[3];
8092         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8093                 t->currentalpha *= r_wateralpha.value;
8094         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8095                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8096         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8097                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8098         if (!(rsurface.ent_flags & RENDER_LIGHT))
8099                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8100         else if (FAKELIGHT_ENABLED)
8101         {
8102                 // no modellight if using fakelight for the map
8103         }
8104         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8105         {
8106                 // pick a model lighting mode
8107                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8108                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8109                 else
8110                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8111         }
8112         if (rsurface.ent_flags & RENDER_ADDITIVE)
8113                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8114         else if (t->currentalpha < 1)
8115                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8116         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8117         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8118                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8119         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8120                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8121         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8122                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8123         if (t->backgroundnumskinframes)
8124                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8125         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8126         {
8127                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8128                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8129         }
8130         else
8131                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8132         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8133         {
8134                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8135                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8136         }
8137         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8138                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8139
8140         // there is no tcmod
8141         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8142         {
8143                 t->currenttexmatrix = r_waterscrollmatrix;
8144                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8145         }
8146         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8147         {
8148                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8149                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8150         }
8151
8152         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8153                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8154         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8155                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8156
8157         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8158         if (t->currentskinframe->qpixels)
8159                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8160         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8161         if (!t->basetexture)
8162                 t->basetexture = r_texture_notexture;
8163         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8164         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8165         t->nmaptexture = t->currentskinframe->nmap;
8166         if (!t->nmaptexture)
8167                 t->nmaptexture = r_texture_blanknormalmap;
8168         t->glosstexture = r_texture_black;
8169         t->glowtexture = t->currentskinframe->glow;
8170         t->fogtexture = t->currentskinframe->fog;
8171         t->reflectmasktexture = t->currentskinframe->reflect;
8172         if (t->backgroundnumskinframes)
8173         {
8174                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8175                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8176                 t->backgroundglosstexture = r_texture_black;
8177                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8178                 if (!t->backgroundnmaptexture)
8179                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8180                 // make sure that if glow is going to be used, both textures are not NULL
8181                 if (!t->backgroundglowtexture && t->glowtexture)
8182                         t->backgroundglowtexture = r_texture_black;
8183                 if (!t->glowtexture && t->backgroundglowtexture)
8184                         t->glowtexture = r_texture_black;
8185         }
8186         else
8187         {
8188                 t->backgroundbasetexture = r_texture_white;
8189                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8190                 t->backgroundglosstexture = r_texture_black;
8191                 t->backgroundglowtexture = NULL;
8192         }
8193         t->specularpower = r_shadow_glossexponent.value;
8194         // TODO: store reference values for these in the texture?
8195         t->specularscale = 0;
8196         if (r_shadow_gloss.integer > 0)
8197         {
8198                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8199                 {
8200                         if (r_shadow_glossintensity.value > 0)
8201                         {
8202                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8203                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8204                                 t->specularscale = r_shadow_glossintensity.value;
8205                         }
8206                 }
8207                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8208                 {
8209                         t->glosstexture = r_texture_white;
8210                         t->backgroundglosstexture = r_texture_white;
8211                         t->specularscale = r_shadow_gloss2intensity.value;
8212                         t->specularpower = r_shadow_gloss2exponent.value;
8213                 }
8214         }
8215         t->specularscale *= t->specularscalemod;
8216         t->specularpower *= t->specularpowermod;
8217         t->rtlightambient = 0;
8218
8219         // lightmaps mode looks bad with dlights using actual texturing, so turn
8220         // off the colormap and glossmap, but leave the normalmap on as it still
8221         // accurately represents the shading involved
8222         if (gl_lightmaps.integer)
8223         {
8224                 t->basetexture = r_texture_grey128;
8225                 t->pantstexture = r_texture_black;
8226                 t->shirttexture = r_texture_black;
8227                 if (gl_lightmaps.integer < 2)
8228                         t->nmaptexture = r_texture_blanknormalmap;
8229                 t->glosstexture = r_texture_black;
8230                 t->glowtexture = NULL;
8231                 t->fogtexture = NULL;
8232                 t->reflectmasktexture = NULL;
8233                 t->backgroundbasetexture = NULL;
8234                 if (gl_lightmaps.integer < 2)
8235                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8236                 t->backgroundglosstexture = r_texture_black;
8237                 t->backgroundglowtexture = NULL;
8238                 t->specularscale = 0;
8239                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8240         }
8241
8242         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8243         VectorClear(t->dlightcolor);
8244         t->currentnumlayers = 0;
8245         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8246         {
8247                 int blendfunc1, blendfunc2;
8248                 qboolean depthmask;
8249                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8250                 {
8251                         blendfunc1 = GL_SRC_ALPHA;
8252                         blendfunc2 = GL_ONE;
8253                 }
8254                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8255                 {
8256                         blendfunc1 = GL_SRC_ALPHA;
8257                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8258                 }
8259                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8260                 {
8261                         blendfunc1 = t->customblendfunc[0];
8262                         blendfunc2 = t->customblendfunc[1];
8263                 }
8264                 else
8265                 {
8266                         blendfunc1 = GL_ONE;
8267                         blendfunc2 = GL_ZERO;
8268                 }
8269                 // don't colormod evilblend textures
8270                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8271                         VectorSet(t->lightmapcolor, 1, 1, 1);
8272                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8273                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8274                 {
8275                         // fullbright is not affected by r_refdef.lightmapintensity
8276                         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]);
8277                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8278                                 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]);
8279                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8280                                 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]);
8281                 }
8282                 else
8283                 {
8284                         vec3_t ambientcolor;
8285                         float colorscale;
8286                         // set the color tint used for lights affecting this surface
8287                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8288                         colorscale = 2;
8289                         // q3bsp has no lightmap updates, so the lightstylevalue that
8290                         // would normally be baked into the lightmap must be
8291                         // applied to the color
8292                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8293                         if (model->type == mod_brushq3)
8294                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8295                         colorscale *= r_refdef.lightmapintensity;
8296                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8297                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8298                         // basic lit geometry
8299                         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]);
8300                         // add pants/shirt if needed
8301                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8302                                 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]);
8303                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8304                                 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]);
8305                         // now add ambient passes if needed
8306                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8307                         {
8308                                 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]);
8309                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8310                                         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]);
8311                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8312                                         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]);
8313                         }
8314                 }
8315                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8316                         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]);
8317                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8318                 {
8319                         // if this is opaque use alpha blend which will darken the earlier
8320                         // passes cheaply.
8321                         //
8322                         // if this is an alpha blended material, all the earlier passes
8323                         // were darkened by fog already, so we only need to add the fog
8324                         // color ontop through the fog mask texture
8325                         //
8326                         // if this is an additive blended material, all the earlier passes
8327                         // were darkened by fog already, and we should not add fog color
8328                         // (because the background was not darkened, there is no fog color
8329                         // that was lost behind it).
8330                         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]);
8331                 }
8332         }
8333
8334         return t->currentframe;
8335 }
8336
8337 rsurfacestate_t rsurface;
8338
8339 void RSurf_ActiveWorldEntity(void)
8340 {
8341         dp_model_t *model = r_refdef.scene.worldmodel;
8342         //if (rsurface.entity == r_refdef.scene.worldentity)
8343         //      return;
8344         rsurface.entity = r_refdef.scene.worldentity;
8345         rsurface.skeleton = NULL;
8346         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8347         rsurface.ent_skinnum = 0;
8348         rsurface.ent_qwskin = -1;
8349         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8350         rsurface.shadertime = r_refdef.scene.time;
8351         rsurface.matrix = identitymatrix;
8352         rsurface.inversematrix = identitymatrix;
8353         rsurface.matrixscale = 1;
8354         rsurface.inversematrixscale = 1;
8355         R_EntityMatrix(&identitymatrix);
8356         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8357         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8358         rsurface.fograngerecip = r_refdef.fograngerecip;
8359         rsurface.fogheightfade = r_refdef.fogheightfade;
8360         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8361         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8362         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8363         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8364         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8365         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8366         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8367         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8368         rsurface.colormod[3] = 1;
8369         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);
8370         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8371         rsurface.frameblend[0].lerp = 1;
8372         rsurface.ent_alttextures = false;
8373         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8374         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8375         rsurface.entityskeletaltransform3x4 = NULL;
8376         rsurface.entityskeletaltransform3x4buffer = NULL;
8377         rsurface.entityskeletaltransform3x4offset = 0;
8378         rsurface.entityskeletaltransform3x4size = 0;;
8379         rsurface.entityskeletalnumtransforms = 0;
8380         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8381         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8382         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8383         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8384         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8385         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8386         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8387         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8388         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8389         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8390         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8391         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8392         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8393         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8394         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8395         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8396         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8397         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8398         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8399         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8400         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8401         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8402         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8403         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8404         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8405         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8406         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8407         rsurface.modelelement3i = model->surfmesh.data_element3i;
8408         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8409         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8410         rsurface.modelelement3s = model->surfmesh.data_element3s;
8411         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8412         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8413         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8414         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8415         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8416         rsurface.modelsurfaces = model->data_surfaces;
8417         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8418         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8419         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8420         rsurface.modelgeneratedvertex = false;
8421         rsurface.batchgeneratedvertex = false;
8422         rsurface.batchfirstvertex = 0;
8423         rsurface.batchnumvertices = 0;
8424         rsurface.batchfirsttriangle = 0;
8425         rsurface.batchnumtriangles = 0;
8426         rsurface.batchvertex3f  = NULL;
8427         rsurface.batchvertex3f_vertexbuffer = NULL;
8428         rsurface.batchvertex3f_bufferoffset = 0;
8429         rsurface.batchsvector3f = NULL;
8430         rsurface.batchsvector3f_vertexbuffer = NULL;
8431         rsurface.batchsvector3f_bufferoffset = 0;
8432         rsurface.batchtvector3f = NULL;
8433         rsurface.batchtvector3f_vertexbuffer = NULL;
8434         rsurface.batchtvector3f_bufferoffset = 0;
8435         rsurface.batchnormal3f  = NULL;
8436         rsurface.batchnormal3f_vertexbuffer = NULL;
8437         rsurface.batchnormal3f_bufferoffset = 0;
8438         rsurface.batchlightmapcolor4f = NULL;
8439         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8440         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8441         rsurface.batchtexcoordtexture2f = NULL;
8442         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8443         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8444         rsurface.batchtexcoordlightmap2f = NULL;
8445         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8446         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8447         rsurface.batchskeletalindex4ub = NULL;
8448         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8449         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8450         rsurface.batchskeletalweight4ub = NULL;
8451         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8452         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8453         rsurface.batchvertexmesh = NULL;
8454         rsurface.batchvertexmesh_vertexbuffer = NULL;
8455         rsurface.batchvertexmesh_bufferoffset = 0;
8456         rsurface.batchelement3i = NULL;
8457         rsurface.batchelement3i_indexbuffer = NULL;
8458         rsurface.batchelement3i_bufferoffset = 0;
8459         rsurface.batchelement3s = NULL;
8460         rsurface.batchelement3s_indexbuffer = NULL;
8461         rsurface.batchelement3s_bufferoffset = 0;
8462         rsurface.passcolor4f = NULL;
8463         rsurface.passcolor4f_vertexbuffer = NULL;
8464         rsurface.passcolor4f_bufferoffset = 0;
8465         rsurface.forcecurrenttextureupdate = false;
8466 }
8467
8468 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8469 {
8470         dp_model_t *model = ent->model;
8471         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8472         //      return;
8473         rsurface.entity = (entity_render_t *)ent;
8474         rsurface.skeleton = ent->skeleton;
8475         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8476         rsurface.ent_skinnum = ent->skinnum;
8477         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;
8478         rsurface.ent_flags = ent->flags;
8479         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8480         rsurface.matrix = ent->matrix;
8481         rsurface.inversematrix = ent->inversematrix;
8482         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8483         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8484         R_EntityMatrix(&rsurface.matrix);
8485         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8486         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8487         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8488         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8489         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8490         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8491         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8492         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8493         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8494         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8495         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8496         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8497         rsurface.colormod[3] = ent->alpha;
8498         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8499         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8500         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8501         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8502         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8503         if (ent->model->brush.submodel && !prepass)
8504         {
8505                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8506                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8507         }
8508         // if the animcache code decided it should use the shader path, skip the deform step
8509         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8510         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8511         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8512         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8513         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8514         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8515         {
8516                 if (ent->animcache_vertex3f)
8517                 {
8518                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8519                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8520                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8521                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8522                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8523                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8524                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8525                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8526                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8527                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8528                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8529                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8530                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8531                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8532                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8533                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8534                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8535                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8536                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8537                 }
8538                 else if (wanttangents)
8539                 {
8540                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8541                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8542                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8543                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8544                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8545                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8546                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8547                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8548                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8549                         rsurface.modelvertexmesh = NULL;
8550                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8551                         rsurface.modelvertexmesh_bufferoffset = 0;
8552                         rsurface.modelvertex3f_vertexbuffer = NULL;
8553                         rsurface.modelvertex3f_bufferoffset = 0;
8554                         rsurface.modelvertex3f_vertexbuffer = 0;
8555                         rsurface.modelvertex3f_bufferoffset = 0;
8556                         rsurface.modelsvector3f_vertexbuffer = 0;
8557                         rsurface.modelsvector3f_bufferoffset = 0;
8558                         rsurface.modeltvector3f_vertexbuffer = 0;
8559                         rsurface.modeltvector3f_bufferoffset = 0;
8560                         rsurface.modelnormal3f_vertexbuffer = 0;
8561                         rsurface.modelnormal3f_bufferoffset = 0;
8562                 }
8563                 else if (wantnormals)
8564                 {
8565                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8566                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8567                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8568                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8569                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8570                         rsurface.modelsvector3f = NULL;
8571                         rsurface.modeltvector3f = NULL;
8572                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8573                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8574                         rsurface.modelvertexmesh = NULL;
8575                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8576                         rsurface.modelvertexmesh_bufferoffset = 0;
8577                         rsurface.modelvertex3f_vertexbuffer = NULL;
8578                         rsurface.modelvertex3f_bufferoffset = 0;
8579                         rsurface.modelvertex3f_vertexbuffer = 0;
8580                         rsurface.modelvertex3f_bufferoffset = 0;
8581                         rsurface.modelsvector3f_vertexbuffer = 0;
8582                         rsurface.modelsvector3f_bufferoffset = 0;
8583                         rsurface.modeltvector3f_vertexbuffer = 0;
8584                         rsurface.modeltvector3f_bufferoffset = 0;
8585                         rsurface.modelnormal3f_vertexbuffer = 0;
8586                         rsurface.modelnormal3f_bufferoffset = 0;
8587                 }
8588                 else
8589                 {
8590                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8591                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8592                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8593                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8594                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8595                         rsurface.modelsvector3f = NULL;
8596                         rsurface.modeltvector3f = NULL;
8597                         rsurface.modelnormal3f = NULL;
8598                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8599                         rsurface.modelvertexmesh = NULL;
8600                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8601                         rsurface.modelvertexmesh_bufferoffset = 0;
8602                         rsurface.modelvertex3f_vertexbuffer = NULL;
8603                         rsurface.modelvertex3f_bufferoffset = 0;
8604                         rsurface.modelvertex3f_vertexbuffer = 0;
8605                         rsurface.modelvertex3f_bufferoffset = 0;
8606                         rsurface.modelsvector3f_vertexbuffer = 0;
8607                         rsurface.modelsvector3f_bufferoffset = 0;
8608                         rsurface.modeltvector3f_vertexbuffer = 0;
8609                         rsurface.modeltvector3f_bufferoffset = 0;
8610                         rsurface.modelnormal3f_vertexbuffer = 0;
8611                         rsurface.modelnormal3f_bufferoffset = 0;
8612                 }
8613                 rsurface.modelgeneratedvertex = true;
8614         }
8615         else
8616         {
8617                 if (rsurface.entityskeletaltransform3x4)
8618                 {
8619                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8620                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8621                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8622                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8623                 }
8624                 else
8625                 {
8626                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8627                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8628                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8629                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8630                 }
8631                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8632                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8633                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8634                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8635                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8636                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8637                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8638                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8639                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8640                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8641                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8642                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8643                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8644                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8645                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8646                 rsurface.modelgeneratedvertex = false;
8647         }
8648         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8649         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8650         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8651         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8652         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8653         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8654         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8655         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8656         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8657         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8658         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8659         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8660         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8661         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8662         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8663         rsurface.modelelement3i = model->surfmesh.data_element3i;
8664         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8665         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8666         rsurface.modelelement3s = model->surfmesh.data_element3s;
8667         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8668         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8669         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8670         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8671         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8672         rsurface.modelsurfaces = model->data_surfaces;
8673         rsurface.batchgeneratedvertex = false;
8674         rsurface.batchfirstvertex = 0;
8675         rsurface.batchnumvertices = 0;
8676         rsurface.batchfirsttriangle = 0;
8677         rsurface.batchnumtriangles = 0;
8678         rsurface.batchvertex3f  = NULL;
8679         rsurface.batchvertex3f_vertexbuffer = NULL;
8680         rsurface.batchvertex3f_bufferoffset = 0;
8681         rsurface.batchsvector3f = NULL;
8682         rsurface.batchsvector3f_vertexbuffer = NULL;
8683         rsurface.batchsvector3f_bufferoffset = 0;
8684         rsurface.batchtvector3f = NULL;
8685         rsurface.batchtvector3f_vertexbuffer = NULL;
8686         rsurface.batchtvector3f_bufferoffset = 0;
8687         rsurface.batchnormal3f  = NULL;
8688         rsurface.batchnormal3f_vertexbuffer = NULL;
8689         rsurface.batchnormal3f_bufferoffset = 0;
8690         rsurface.batchlightmapcolor4f = NULL;
8691         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8692         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8693         rsurface.batchtexcoordtexture2f = NULL;
8694         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8695         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8696         rsurface.batchtexcoordlightmap2f = NULL;
8697         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8698         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8699         rsurface.batchskeletalindex4ub = NULL;
8700         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8701         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8702         rsurface.batchskeletalweight4ub = NULL;
8703         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8704         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8705         rsurface.batchvertexmesh = NULL;
8706         rsurface.batchvertexmesh_vertexbuffer = NULL;
8707         rsurface.batchvertexmesh_bufferoffset = 0;
8708         rsurface.batchelement3i = NULL;
8709         rsurface.batchelement3i_indexbuffer = NULL;
8710         rsurface.batchelement3i_bufferoffset = 0;
8711         rsurface.batchelement3s = NULL;
8712         rsurface.batchelement3s_indexbuffer = NULL;
8713         rsurface.batchelement3s_bufferoffset = 0;
8714         rsurface.passcolor4f = NULL;
8715         rsurface.passcolor4f_vertexbuffer = NULL;
8716         rsurface.passcolor4f_bufferoffset = 0;
8717         rsurface.forcecurrenttextureupdate = false;
8718 }
8719
8720 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)
8721 {
8722         rsurface.entity = r_refdef.scene.worldentity;
8723         rsurface.skeleton = NULL;
8724         rsurface.ent_skinnum = 0;
8725         rsurface.ent_qwskin = -1;
8726         rsurface.ent_flags = entflags;
8727         rsurface.shadertime = r_refdef.scene.time - shadertime;
8728         rsurface.modelnumvertices = numvertices;
8729         rsurface.modelnumtriangles = numtriangles;
8730         rsurface.matrix = *matrix;
8731         rsurface.inversematrix = *inversematrix;
8732         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8733         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8734         R_EntityMatrix(&rsurface.matrix);
8735         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8736         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8737         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8738         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8739         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8740         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8741         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8742         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8743         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8744         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8745         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8746         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8747         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);
8748         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8749         rsurface.frameblend[0].lerp = 1;
8750         rsurface.ent_alttextures = false;
8751         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8752         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8753         rsurface.entityskeletaltransform3x4 = NULL;
8754         rsurface.entityskeletaltransform3x4buffer = NULL;
8755         rsurface.entityskeletaltransform3x4offset = 0;
8756         rsurface.entityskeletaltransform3x4size = 0;
8757         rsurface.entityskeletalnumtransforms = 0;
8758         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8759         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8760         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8761         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8762         if (wanttangents)
8763         {
8764                 rsurface.modelvertex3f = (float *)vertex3f;
8765                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8766                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8767                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8768         }
8769         else if (wantnormals)
8770         {
8771                 rsurface.modelvertex3f = (float *)vertex3f;
8772                 rsurface.modelsvector3f = NULL;
8773                 rsurface.modeltvector3f = NULL;
8774                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8775         }
8776         else
8777         {
8778                 rsurface.modelvertex3f = (float *)vertex3f;
8779                 rsurface.modelsvector3f = NULL;
8780                 rsurface.modeltvector3f = NULL;
8781                 rsurface.modelnormal3f = NULL;
8782         }
8783         rsurface.modelvertexmesh = NULL;
8784         rsurface.modelvertexmesh_vertexbuffer = NULL;
8785         rsurface.modelvertexmesh_bufferoffset = 0;
8786         rsurface.modelvertex3f_vertexbuffer = 0;
8787         rsurface.modelvertex3f_bufferoffset = 0;
8788         rsurface.modelsvector3f_vertexbuffer = 0;
8789         rsurface.modelsvector3f_bufferoffset = 0;
8790         rsurface.modeltvector3f_vertexbuffer = 0;
8791         rsurface.modeltvector3f_bufferoffset = 0;
8792         rsurface.modelnormal3f_vertexbuffer = 0;
8793         rsurface.modelnormal3f_bufferoffset = 0;
8794         rsurface.modelgeneratedvertex = true;
8795         rsurface.modellightmapcolor4f  = (float *)color4f;
8796         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8797         rsurface.modellightmapcolor4f_bufferoffset = 0;
8798         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8799         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8800         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8801         rsurface.modeltexcoordlightmap2f  = NULL;
8802         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8803         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8804         rsurface.modelskeletalindex4ub = NULL;
8805         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8806         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8807         rsurface.modelskeletalweight4ub = NULL;
8808         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8809         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8810         rsurface.modelelement3i = (int *)element3i;
8811         rsurface.modelelement3i_indexbuffer = NULL;
8812         rsurface.modelelement3i_bufferoffset = 0;
8813         rsurface.modelelement3s = (unsigned short *)element3s;
8814         rsurface.modelelement3s_indexbuffer = NULL;
8815         rsurface.modelelement3s_bufferoffset = 0;
8816         rsurface.modellightmapoffsets = NULL;
8817         rsurface.modelsurfaces = NULL;
8818         rsurface.batchgeneratedvertex = false;
8819         rsurface.batchfirstvertex = 0;
8820         rsurface.batchnumvertices = 0;
8821         rsurface.batchfirsttriangle = 0;
8822         rsurface.batchnumtriangles = 0;
8823         rsurface.batchvertex3f  = NULL;
8824         rsurface.batchvertex3f_vertexbuffer = NULL;
8825         rsurface.batchvertex3f_bufferoffset = 0;
8826         rsurface.batchsvector3f = NULL;
8827         rsurface.batchsvector3f_vertexbuffer = NULL;
8828         rsurface.batchsvector3f_bufferoffset = 0;
8829         rsurface.batchtvector3f = NULL;
8830         rsurface.batchtvector3f_vertexbuffer = NULL;
8831         rsurface.batchtvector3f_bufferoffset = 0;
8832         rsurface.batchnormal3f  = NULL;
8833         rsurface.batchnormal3f_vertexbuffer = NULL;
8834         rsurface.batchnormal3f_bufferoffset = 0;
8835         rsurface.batchlightmapcolor4f = NULL;
8836         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8837         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8838         rsurface.batchtexcoordtexture2f = NULL;
8839         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8840         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8841         rsurface.batchtexcoordlightmap2f = NULL;
8842         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8843         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8844         rsurface.batchskeletalindex4ub = NULL;
8845         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8846         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8847         rsurface.batchskeletalweight4ub = NULL;
8848         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8849         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8850         rsurface.batchvertexmesh = NULL;
8851         rsurface.batchvertexmesh_vertexbuffer = NULL;
8852         rsurface.batchvertexmesh_bufferoffset = 0;
8853         rsurface.batchelement3i = NULL;
8854         rsurface.batchelement3i_indexbuffer = NULL;
8855         rsurface.batchelement3i_bufferoffset = 0;
8856         rsurface.batchelement3s = NULL;
8857         rsurface.batchelement3s_indexbuffer = NULL;
8858         rsurface.batchelement3s_bufferoffset = 0;
8859         rsurface.passcolor4f = NULL;
8860         rsurface.passcolor4f_vertexbuffer = NULL;
8861         rsurface.passcolor4f_bufferoffset = 0;
8862         rsurface.forcecurrenttextureupdate = true;
8863
8864         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8865         {
8866                 if ((wantnormals || wanttangents) && !normal3f)
8867                 {
8868                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8869                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8870                 }
8871                 if (wanttangents && !svector3f)
8872                 {
8873                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8874                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8875                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8876                 }
8877         }
8878 }
8879
8880 float RSurf_FogPoint(const float *v)
8881 {
8882         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8883         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8884         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8885         float FogHeightFade = r_refdef.fogheightfade;
8886         float fogfrac;
8887         unsigned int fogmasktableindex;
8888         if (r_refdef.fogplaneviewabove)
8889                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8890         else
8891                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8892         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8893         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8894 }
8895
8896 float RSurf_FogVertex(const float *v)
8897 {
8898         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8899         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8900         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8901         float FogHeightFade = rsurface.fogheightfade;
8902         float fogfrac;
8903         unsigned int fogmasktableindex;
8904         if (r_refdef.fogplaneviewabove)
8905                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8906         else
8907                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8908         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8909         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8910 }
8911
8912 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8913 {
8914         int i;
8915         for (i = 0;i < numelements;i++)
8916                 outelement3i[i] = inelement3i[i] + adjust;
8917 }
8918
8919 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8920 extern cvar_t gl_vbo;
8921 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8922 {
8923         int deformindex;
8924         int firsttriangle;
8925         int numtriangles;
8926         int firstvertex;
8927         int endvertex;
8928         int numvertices;
8929         int surfacefirsttriangle;
8930         int surfacenumtriangles;
8931         int surfacefirstvertex;
8932         int surfaceendvertex;
8933         int surfacenumvertices;
8934         int batchnumsurfaces = texturenumsurfaces;
8935         int batchnumvertices;
8936         int batchnumtriangles;
8937         int needsupdate;
8938         int i, j;
8939         qboolean gaps;
8940         qboolean dynamicvertex;
8941         float amplitude;
8942         float animpos;
8943         float scale;
8944         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8945         float waveparms[4];
8946         unsigned char *ub;
8947         q3shaderinfo_deform_t *deform;
8948         const msurface_t *surface, *firstsurface;
8949         r_vertexmesh_t *vertexmesh;
8950         if (!texturenumsurfaces)
8951                 return;
8952         // find vertex range of this surface batch
8953         gaps = false;
8954         firstsurface = texturesurfacelist[0];
8955         firsttriangle = firstsurface->num_firsttriangle;
8956         batchnumvertices = 0;
8957         batchnumtriangles = 0;
8958         firstvertex = endvertex = firstsurface->num_firstvertex;
8959         for (i = 0;i < texturenumsurfaces;i++)
8960         {
8961                 surface = texturesurfacelist[i];
8962                 if (surface != firstsurface + i)
8963                         gaps = true;
8964                 surfacefirstvertex = surface->num_firstvertex;
8965                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8966                 surfacenumvertices = surface->num_vertices;
8967                 surfacenumtriangles = surface->num_triangles;
8968                 if (firstvertex > surfacefirstvertex)
8969                         firstvertex = surfacefirstvertex;
8970                 if (endvertex < surfaceendvertex)
8971                         endvertex = surfaceendvertex;
8972                 batchnumvertices += surfacenumvertices;
8973                 batchnumtriangles += surfacenumtriangles;
8974         }
8975
8976         r_refdef.stats[r_stat_batch_batches]++;
8977         if (gaps)
8978                 r_refdef.stats[r_stat_batch_withgaps]++;
8979         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8980         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8981         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8982
8983         // we now know the vertex range used, and if there are any gaps in it
8984         rsurface.batchfirstvertex = firstvertex;
8985         rsurface.batchnumvertices = endvertex - firstvertex;
8986         rsurface.batchfirsttriangle = firsttriangle;
8987         rsurface.batchnumtriangles = batchnumtriangles;
8988
8989         // this variable holds flags for which properties have been updated that
8990         // may require regenerating vertexmesh array...
8991         needsupdate = 0;
8992
8993         // check if any dynamic vertex processing must occur
8994         dynamicvertex = false;
8995
8996         // a cvar to force the dynamic vertex path to be taken, for debugging
8997         if (r_batch_debugdynamicvertexpath.integer)
8998         {
8999                 if (!dynamicvertex)
9000                 {
9001                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9002                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9003                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9004                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9005                 }
9006                 dynamicvertex = true;
9007         }
9008
9009         // if there is a chance of animated vertex colors, it's a dynamic batch
9010         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9011         {
9012                 if (!dynamicvertex)
9013                 {
9014                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9015                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9016                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9017                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9018                 }
9019                 dynamicvertex = true;
9020                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9021         }
9022
9023         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9024         {
9025                 switch (deform->deform)
9026                 {
9027                 default:
9028                 case Q3DEFORM_PROJECTIONSHADOW:
9029                 case Q3DEFORM_TEXT0:
9030                 case Q3DEFORM_TEXT1:
9031                 case Q3DEFORM_TEXT2:
9032                 case Q3DEFORM_TEXT3:
9033                 case Q3DEFORM_TEXT4:
9034                 case Q3DEFORM_TEXT5:
9035                 case Q3DEFORM_TEXT6:
9036                 case Q3DEFORM_TEXT7:
9037                 case Q3DEFORM_NONE:
9038                         break;
9039                 case Q3DEFORM_AUTOSPRITE:
9040                         if (!dynamicvertex)
9041                         {
9042                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9043                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9044                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9045                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9046                         }
9047                         dynamicvertex = true;
9048                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9049                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9050                         break;
9051                 case Q3DEFORM_AUTOSPRITE2:
9052                         if (!dynamicvertex)
9053                         {
9054                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9055                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9056                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9057                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9058                         }
9059                         dynamicvertex = true;
9060                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9061                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9062                         break;
9063                 case Q3DEFORM_NORMAL:
9064                         if (!dynamicvertex)
9065                         {
9066                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9067                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9068                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9069                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9070                         }
9071                         dynamicvertex = true;
9072                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9073                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9074                         break;
9075                 case Q3DEFORM_WAVE:
9076                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9077                                 break; // if wavefunc is a nop, ignore this transform
9078                         if (!dynamicvertex)
9079                         {
9080                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9081                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9082                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9083                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9084                         }
9085                         dynamicvertex = true;
9086                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9087                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9088                         break;
9089                 case Q3DEFORM_BULGE:
9090                         if (!dynamicvertex)
9091                         {
9092                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9093                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9094                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9095                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9096                         }
9097                         dynamicvertex = true;
9098                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9099                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9100                         break;
9101                 case Q3DEFORM_MOVE:
9102                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9103                                 break; // if wavefunc is a nop, ignore this transform
9104                         if (!dynamicvertex)
9105                         {
9106                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9107                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9108                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9109                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9110                         }
9111                         dynamicvertex = true;
9112                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9113                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9114                         break;
9115                 }
9116         }
9117         switch(rsurface.texture->tcgen.tcgen)
9118         {
9119         default:
9120         case Q3TCGEN_TEXTURE:
9121                 break;
9122         case Q3TCGEN_LIGHTMAP:
9123                 if (!dynamicvertex)
9124                 {
9125                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9126                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9127                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9128                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9129                 }
9130                 dynamicvertex = true;
9131                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9132                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9133                 break;
9134         case Q3TCGEN_VECTOR:
9135                 if (!dynamicvertex)
9136                 {
9137                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9138                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9139                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9140                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9141                 }
9142                 dynamicvertex = true;
9143                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9144                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9145                 break;
9146         case Q3TCGEN_ENVIRONMENT:
9147                 if (!dynamicvertex)
9148                 {
9149                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9150                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9151                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9152                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9153                 }
9154                 dynamicvertex = true;
9155                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9156                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9157                 break;
9158         }
9159         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9160         {
9161                 if (!dynamicvertex)
9162                 {
9163                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9164                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9165                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9166                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9167                 }
9168                 dynamicvertex = true;
9169                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9170                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9171         }
9172
9173         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9174         {
9175                 if (!dynamicvertex)
9176                 {
9177                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9178                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9179                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9180                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9181                 }
9182                 dynamicvertex = true;
9183                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9184         }
9185
9186         // when the model data has no vertex buffer (dynamic mesh), we need to
9187         // eliminate gaps
9188         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9189                 batchneed |= BATCHNEED_NOGAPS;
9190
9191         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9192         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9193         // we ensure this by treating the vertex batch as dynamic...
9194         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9195         {
9196                 if (!dynamicvertex)
9197                 {
9198                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9199                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9200                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9201                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9202                 }
9203                 dynamicvertex = true;
9204         }
9205
9206         if (dynamicvertex)
9207         {
9208                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9209                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9210                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9211                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9212                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9213                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9214                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9215                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9216         }
9217
9218         // if needsupdate, we have to do a dynamic vertex batch for sure
9219         if (needsupdate & batchneed)
9220         {
9221                 if (!dynamicvertex)
9222                 {
9223                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9224                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9225                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9226                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9227                 }
9228                 dynamicvertex = true;
9229         }
9230
9231         // see if we need to build vertexmesh from arrays
9232         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9233         {
9234                 if (!dynamicvertex)
9235                 {
9236                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9237                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9238                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9239                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9240                 }
9241                 dynamicvertex = true;
9242         }
9243
9244         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9245         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9246                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9247
9248         rsurface.batchvertex3f = rsurface.modelvertex3f;
9249         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9250         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9251         rsurface.batchsvector3f = rsurface.modelsvector3f;
9252         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9253         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9254         rsurface.batchtvector3f = rsurface.modeltvector3f;
9255         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9256         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9257         rsurface.batchnormal3f = rsurface.modelnormal3f;
9258         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9259         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9260         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9261         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9262         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9263         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9264         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9265         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9266         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9267         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9268         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9269         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9270         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9271         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9272         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9273         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9274         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9275         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9276         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9277         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9278         rsurface.batchelement3i = rsurface.modelelement3i;
9279         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9280         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9281         rsurface.batchelement3s = rsurface.modelelement3s;
9282         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9283         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9284         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9285         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9286         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9287         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9288         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9289
9290         // if any dynamic vertex processing has to occur in software, we copy the
9291         // entire surface list together before processing to rebase the vertices
9292         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9293         //
9294         // if any gaps exist and we do not have a static vertex buffer, we have to
9295         // copy the surface list together to avoid wasting upload bandwidth on the
9296         // vertices in the gaps.
9297         //
9298         // if gaps exist and we have a static vertex buffer, we can choose whether
9299         // to combine the index buffer ranges into one dynamic index buffer or
9300         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9301         //
9302         // in many cases the batch is reduced to one draw call.
9303
9304         rsurface.batchmultidraw = false;
9305         rsurface.batchmultidrawnumsurfaces = 0;
9306         rsurface.batchmultidrawsurfacelist = NULL;
9307
9308         if (!dynamicvertex)
9309         {
9310                 // static vertex data, just set pointers...
9311                 rsurface.batchgeneratedvertex = false;
9312                 // if there are gaps, we want to build a combined index buffer,
9313                 // otherwise use the original static buffer with an appropriate offset
9314                 if (gaps)
9315                 {
9316                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9317                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9318                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9319                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9320                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9321                         {
9322                                 rsurface.batchmultidraw = true;
9323                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9324                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9325                                 return;
9326                         }
9327                         // build a new triangle elements array for this batch
9328                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9329                         rsurface.batchfirsttriangle = 0;
9330                         numtriangles = 0;
9331                         for (i = 0;i < texturenumsurfaces;i++)
9332                         {
9333                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9334                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9335                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9336                                 numtriangles += surfacenumtriangles;
9337                         }
9338                         rsurface.batchelement3i_indexbuffer = NULL;
9339                         rsurface.batchelement3i_bufferoffset = 0;
9340                         rsurface.batchelement3s = NULL;
9341                         rsurface.batchelement3s_indexbuffer = NULL;
9342                         rsurface.batchelement3s_bufferoffset = 0;
9343                         if (endvertex <= 65536)
9344                         {
9345                                 // make a 16bit (unsigned short) index array if possible
9346                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9347                                 for (i = 0;i < numtriangles*3;i++)
9348                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9349                         }
9350                         // upload buffer data for the copytriangles batch
9351                         if ((r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9352                         {
9353                                 if (rsurface.batchelement3s)
9354                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9355                                 else if (rsurface.batchelement3i)
9356                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9357                         }
9358                 }
9359                 else
9360                 {
9361                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9362                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9363                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9364                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9365                 }
9366                 return;
9367         }
9368
9369         // something needs software processing, do it for real...
9370         // we only directly handle separate array data in this case and then
9371         // generate interleaved data if needed...
9372         rsurface.batchgeneratedvertex = true;
9373         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9374         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9375         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9376         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9377
9378         // now copy the vertex data into a combined array and make an index array
9379         // (this is what Quake3 does all the time)
9380         // we also apply any skeletal animation here that would have been done in
9381         // the vertex shader, because most of the dynamic vertex animation cases
9382         // need actual vertex positions and normals
9383         //if (dynamicvertex)
9384         {
9385                 rsurface.batchvertexmesh = NULL;
9386                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9387                 rsurface.batchvertexmesh_bufferoffset = 0;
9388                 rsurface.batchvertex3f = NULL;
9389                 rsurface.batchvertex3f_vertexbuffer = NULL;
9390                 rsurface.batchvertex3f_bufferoffset = 0;
9391                 rsurface.batchsvector3f = NULL;
9392                 rsurface.batchsvector3f_vertexbuffer = NULL;
9393                 rsurface.batchsvector3f_bufferoffset = 0;
9394                 rsurface.batchtvector3f = NULL;
9395                 rsurface.batchtvector3f_vertexbuffer = NULL;
9396                 rsurface.batchtvector3f_bufferoffset = 0;
9397                 rsurface.batchnormal3f = NULL;
9398                 rsurface.batchnormal3f_vertexbuffer = NULL;
9399                 rsurface.batchnormal3f_bufferoffset = 0;
9400                 rsurface.batchlightmapcolor4f = NULL;
9401                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9402                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9403                 rsurface.batchtexcoordtexture2f = NULL;
9404                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9405                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9406                 rsurface.batchtexcoordlightmap2f = NULL;
9407                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9408                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9409                 rsurface.batchskeletalindex4ub = NULL;
9410                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9411                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9412                 rsurface.batchskeletalweight4ub = NULL;
9413                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9414                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9415                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9416                 rsurface.batchelement3i_indexbuffer = NULL;
9417                 rsurface.batchelement3i_bufferoffset = 0;
9418                 rsurface.batchelement3s = NULL;
9419                 rsurface.batchelement3s_indexbuffer = NULL;
9420                 rsurface.batchelement3s_bufferoffset = 0;
9421                 rsurface.batchskeletaltransform3x4buffer = NULL;
9422                 rsurface.batchskeletaltransform3x4offset = 0;
9423                 rsurface.batchskeletaltransform3x4size = 0;
9424                 // we'll only be setting up certain arrays as needed
9425                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9426                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9427                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9428                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9429                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9430                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9431                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9432                 {
9433                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9434                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9435                 }
9436                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9437                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9438                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9439                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9440                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9441                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9442                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9443                 {
9444                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9445                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9446                 }
9447                 numvertices = 0;
9448                 numtriangles = 0;
9449                 for (i = 0;i < texturenumsurfaces;i++)
9450                 {
9451                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9452                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9453                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9454                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9455                         // copy only the data requested
9456                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9457                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9458                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9459                         {
9460                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9461                                 {
9462                                         if (rsurface.batchvertex3f)
9463                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9464                                         else
9465                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9466                                 }
9467                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9468                                 {
9469                                         if (rsurface.modelnormal3f)
9470                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9471                                         else
9472                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9473                                 }
9474                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9475                                 {
9476                                         if (rsurface.modelsvector3f)
9477                                         {
9478                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9479                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9480                                         }
9481                                         else
9482                                         {
9483                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9484                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9485                                         }
9486                                 }
9487                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9488                                 {
9489                                         if (rsurface.modellightmapcolor4f)
9490                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9491                                         else
9492                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9493                                 }
9494                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9495                                 {
9496                                         if (rsurface.modeltexcoordtexture2f)
9497                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9498                                         else
9499                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9500                                 }
9501                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9502                                 {
9503                                         if (rsurface.modeltexcoordlightmap2f)
9504                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9505                                         else
9506                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9507                                 }
9508                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9509                                 {
9510                                         if (rsurface.modelskeletalindex4ub)
9511                                         {
9512                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9513                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9514                                         }
9515                                         else
9516                                         {
9517                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9518                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9519                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9520                                                 for (j = 0;j < surfacenumvertices;j++)
9521                                                         ub[j*4] = 255;
9522                                         }
9523                                 }
9524                         }
9525                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9526                         numvertices += surfacenumvertices;
9527                         numtriangles += surfacenumtriangles;
9528                 }
9529
9530                 // generate a 16bit index array as well if possible
9531                 // (in general, dynamic batches fit)
9532                 if (numvertices <= 65536)
9533                 {
9534                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9535                         for (i = 0;i < numtriangles*3;i++)
9536                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9537                 }
9538
9539                 // since we've copied everything, the batch now starts at 0
9540                 rsurface.batchfirstvertex = 0;
9541                 rsurface.batchnumvertices = batchnumvertices;
9542                 rsurface.batchfirsttriangle = 0;
9543                 rsurface.batchnumtriangles = batchnumtriangles;
9544         }
9545
9546         // apply skeletal animation that would have been done in the vertex shader
9547         if (rsurface.batchskeletaltransform3x4)
9548         {
9549                 const unsigned char *si;
9550                 const unsigned char *sw;
9551                 const float *t[4];
9552                 const float *b = rsurface.batchskeletaltransform3x4;
9553                 float *vp, *vs, *vt, *vn;
9554                 float w[4];
9555                 float m[3][4], n[3][4];
9556                 float tp[3], ts[3], tt[3], tn[3];
9557                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9558                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9559                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9560                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9561                 si = rsurface.batchskeletalindex4ub;
9562                 sw = rsurface.batchskeletalweight4ub;
9563                 vp = rsurface.batchvertex3f;
9564                 vs = rsurface.batchsvector3f;
9565                 vt = rsurface.batchtvector3f;
9566                 vn = rsurface.batchnormal3f;
9567                 memset(m[0], 0, sizeof(m));
9568                 memset(n[0], 0, sizeof(n));
9569                 for (i = 0;i < batchnumvertices;i++)
9570                 {
9571                         t[0] = b + si[0]*12;
9572                         if (sw[0] == 255)
9573                         {
9574                                 // common case - only one matrix
9575                                 m[0][0] = t[0][ 0];
9576                                 m[0][1] = t[0][ 1];
9577                                 m[0][2] = t[0][ 2];
9578                                 m[0][3] = t[0][ 3];
9579                                 m[1][0] = t[0][ 4];
9580                                 m[1][1] = t[0][ 5];
9581                                 m[1][2] = t[0][ 6];
9582                                 m[1][3] = t[0][ 7];
9583                                 m[2][0] = t[0][ 8];
9584                                 m[2][1] = t[0][ 9];
9585                                 m[2][2] = t[0][10];
9586                                 m[2][3] = t[0][11];
9587                         }
9588                         else if (sw[2] + sw[3])
9589                         {
9590                                 // blend 4 matrices
9591                                 t[1] = b + si[1]*12;
9592                                 t[2] = b + si[2]*12;
9593                                 t[3] = b + si[3]*12;
9594                                 w[0] = sw[0] * (1.0f / 255.0f);
9595                                 w[1] = sw[1] * (1.0f / 255.0f);
9596                                 w[2] = sw[2] * (1.0f / 255.0f);
9597                                 w[3] = sw[3] * (1.0f / 255.0f);
9598                                 // blend the matrices
9599                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9600                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9601                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9602                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9603                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9604                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9605                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9606                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9607                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9608                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9609                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9610                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9611                         }
9612                         else
9613                         {
9614                                 // blend 2 matrices
9615                                 t[1] = b + si[1]*12;
9616                                 w[0] = sw[0] * (1.0f / 255.0f);
9617                                 w[1] = sw[1] * (1.0f / 255.0f);
9618                                 // blend the matrices
9619                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9620                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9621                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9622                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9623                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9624                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9625                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9626                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9627                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9628                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9629                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9630                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9631                         }
9632                         si += 4;
9633                         sw += 4;
9634                         // modify the vertex
9635                         VectorCopy(vp, tp);
9636                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9637                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9638                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9639                         vp += 3;
9640                         if (vn)
9641                         {
9642                                 // the normal transformation matrix is a set of cross products...
9643                                 CrossProduct(m[1], m[2], n[0]);
9644                                 CrossProduct(m[2], m[0], n[1]);
9645                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9646                                 VectorCopy(vn, tn);
9647                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9648                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9649                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9650                                 VectorNormalize(vn);
9651                                 vn += 3;
9652                                 if (vs)
9653                                 {
9654                                         VectorCopy(vs, ts);
9655                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9656                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9657                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9658                                         VectorNormalize(vs);
9659                                         vs += 3;
9660                                         VectorCopy(vt, tt);
9661                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9662                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9663                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9664                                         VectorNormalize(vt);
9665                                         vt += 3;
9666                                 }
9667                         }
9668                 }
9669                 rsurface.batchskeletaltransform3x4 = NULL;
9670                 rsurface.batchskeletalnumtransforms = 0;
9671         }
9672
9673         // q1bsp surfaces rendered in vertex color mode have to have colors
9674         // calculated based on lightstyles
9675         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9676         {
9677                 // generate color arrays for the surfaces in this list
9678                 int c[4];
9679                 int scale;
9680                 int size3;
9681                 const int *offsets;
9682                 const unsigned char *lm;
9683                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9684                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9685                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9686                 numvertices = 0;
9687                 for (i = 0;i < texturenumsurfaces;i++)
9688                 {
9689                         surface = texturesurfacelist[i];
9690                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9691                         surfacenumvertices = surface->num_vertices;
9692                         if (surface->lightmapinfo->samples)
9693                         {
9694                                 for (j = 0;j < surfacenumvertices;j++)
9695                                 {
9696                                         lm = surface->lightmapinfo->samples + offsets[j];
9697                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9698                                         VectorScale(lm, scale, c);
9699                                         if (surface->lightmapinfo->styles[1] != 255)
9700                                         {
9701                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9702                                                 lm += size3;
9703                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9704                                                 VectorMA(c, scale, lm, c);
9705                                                 if (surface->lightmapinfo->styles[2] != 255)
9706                                                 {
9707                                                         lm += size3;
9708                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9709                                                         VectorMA(c, scale, lm, c);
9710                                                         if (surface->lightmapinfo->styles[3] != 255)
9711                                                         {
9712                                                                 lm += size3;
9713                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9714                                                                 VectorMA(c, scale, lm, c);
9715                                                         }
9716                                                 }
9717                                         }
9718                                         c[0] >>= 7;
9719                                         c[1] >>= 7;
9720                                         c[2] >>= 7;
9721                                         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);
9722                                         numvertices++;
9723                                 }
9724                         }
9725                         else
9726                         {
9727                                 for (j = 0;j < surfacenumvertices;j++)
9728                                 {
9729                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9730                                         numvertices++;
9731                                 }
9732                         }
9733                 }
9734         }
9735
9736         // if vertices are deformed (sprite flares and things in maps, possibly
9737         // water waves, bulges and other deformations), modify the copied vertices
9738         // in place
9739         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9740         {
9741                 switch (deform->deform)
9742                 {
9743                 default:
9744                 case Q3DEFORM_PROJECTIONSHADOW:
9745                 case Q3DEFORM_TEXT0:
9746                 case Q3DEFORM_TEXT1:
9747                 case Q3DEFORM_TEXT2:
9748                 case Q3DEFORM_TEXT3:
9749                 case Q3DEFORM_TEXT4:
9750                 case Q3DEFORM_TEXT5:
9751                 case Q3DEFORM_TEXT6:
9752                 case Q3DEFORM_TEXT7:
9753                 case Q3DEFORM_NONE:
9754                         break;
9755                 case Q3DEFORM_AUTOSPRITE:
9756                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9757                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9758                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9759                         VectorNormalize(newforward);
9760                         VectorNormalize(newright);
9761                         VectorNormalize(newup);
9762 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9763 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9764 //                      rsurface.batchvertex3f_bufferoffset = 0;
9765 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9766 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9767 //                      rsurface.batchsvector3f_bufferoffset = 0;
9768 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9769 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9770 //                      rsurface.batchtvector3f_bufferoffset = 0;
9771 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9772 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9773 //                      rsurface.batchnormal3f_bufferoffset = 0;
9774                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9775                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9776                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9777                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9778                                 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);
9779                         // a single autosprite surface can contain multiple sprites...
9780                         for (j = 0;j < batchnumvertices - 3;j += 4)
9781                         {
9782                                 VectorClear(center);
9783                                 for (i = 0;i < 4;i++)
9784                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9785                                 VectorScale(center, 0.25f, center);
9786                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9787                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9788                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9789                                 for (i = 0;i < 4;i++)
9790                                 {
9791                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9792                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9793                                 }
9794                         }
9795                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9796                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9797                         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);
9798                         break;
9799                 case Q3DEFORM_AUTOSPRITE2:
9800                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9801                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9802                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9803                         VectorNormalize(newforward);
9804                         VectorNormalize(newright);
9805                         VectorNormalize(newup);
9806 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9807 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9808 //                      rsurface.batchvertex3f_bufferoffset = 0;
9809                         {
9810                                 const float *v1, *v2;
9811                                 vec3_t start, end;
9812                                 float f, l;
9813                                 struct
9814                                 {
9815                                         float length2;
9816                                         const float *v1;
9817                                         const float *v2;
9818                                 }
9819                                 shortest[2];
9820                                 memset(shortest, 0, sizeof(shortest));
9821                                 // a single autosprite surface can contain multiple sprites...
9822                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9823                                 {
9824                                         VectorClear(center);
9825                                         for (i = 0;i < 4;i++)
9826                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9827                                         VectorScale(center, 0.25f, center);
9828                                         // find the two shortest edges, then use them to define the
9829                                         // axis vectors for rotating around the central axis
9830                                         for (i = 0;i < 6;i++)
9831                                         {
9832                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9833                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9834                                                 l = VectorDistance2(v1, v2);
9835                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9836                                                 if (v1[2] != v2[2])
9837                                                         l += (1.0f / 1024.0f);
9838                                                 if (shortest[0].length2 > l || i == 0)
9839                                                 {
9840                                                         shortest[1] = shortest[0];
9841                                                         shortest[0].length2 = l;
9842                                                         shortest[0].v1 = v1;
9843                                                         shortest[0].v2 = v2;
9844                                                 }
9845                                                 else if (shortest[1].length2 > l || i == 1)
9846                                                 {
9847                                                         shortest[1].length2 = l;
9848                                                         shortest[1].v1 = v1;
9849                                                         shortest[1].v2 = v2;
9850                                                 }
9851                                         }
9852                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9853                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9854                                         // this calculates the right vector from the shortest edge
9855                                         // and the up vector from the edge midpoints
9856                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9857                                         VectorNormalize(right);
9858                                         VectorSubtract(end, start, up);
9859                                         VectorNormalize(up);
9860                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9861                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9862                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9863                                         VectorNegate(forward, forward);
9864                                         VectorReflect(forward, 0, up, forward);
9865                                         VectorNormalize(forward);
9866                                         CrossProduct(up, forward, newright);
9867                                         VectorNormalize(newright);
9868                                         // rotate the quad around the up axis vector, this is made
9869                                         // especially easy by the fact we know the quad is flat,
9870                                         // so we only have to subtract the center position and
9871                                         // measure distance along the right vector, and then
9872                                         // multiply that by the newright vector and add back the
9873                                         // center position
9874                                         // we also need to subtract the old position to undo the
9875                                         // displacement from the center, which we do with a
9876                                         // DotProduct, the subtraction/addition of center is also
9877                                         // optimized into DotProducts here
9878                                         l = DotProduct(right, center);
9879                                         for (i = 0;i < 4;i++)
9880                                         {
9881                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9882                                                 f = DotProduct(right, v1) - l;
9883                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9884                                         }
9885                                 }
9886                         }
9887                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9888                         {
9889 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9890 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9891 //                              rsurface.batchnormal3f_bufferoffset = 0;
9892                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9893                         }
9894                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9895                         {
9896 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9897 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9898 //                              rsurface.batchsvector3f_bufferoffset = 0;
9899 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9900 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9901 //                              rsurface.batchtvector3f_bufferoffset = 0;
9902                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9903                         }
9904                         break;
9905                 case Q3DEFORM_NORMAL:
9906                         // deform the normals to make reflections wavey
9907                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9908                         rsurface.batchnormal3f_vertexbuffer = NULL;
9909                         rsurface.batchnormal3f_bufferoffset = 0;
9910                         for (j = 0;j < batchnumvertices;j++)
9911                         {
9912                                 float vertex[3];
9913                                 float *normal = rsurface.batchnormal3f + 3*j;
9914                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9915                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9916                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9917                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9918                                 VectorNormalize(normal);
9919                         }
9920                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9921                         {
9922 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9923 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9924 //                              rsurface.batchsvector3f_bufferoffset = 0;
9925 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9926 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9927 //                              rsurface.batchtvector3f_bufferoffset = 0;
9928                                 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);
9929                         }
9930                         break;
9931                 case Q3DEFORM_WAVE:
9932                         // deform vertex array to make wavey water and flags and such
9933                         waveparms[0] = deform->waveparms[0];
9934                         waveparms[1] = deform->waveparms[1];
9935                         waveparms[2] = deform->waveparms[2];
9936                         waveparms[3] = deform->waveparms[3];
9937                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9938                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9939                         // this is how a divisor of vertex influence on deformation
9940                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9941                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9942 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9943 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9944 //                      rsurface.batchvertex3f_bufferoffset = 0;
9945 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9946 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9947 //                      rsurface.batchnormal3f_bufferoffset = 0;
9948                         for (j = 0;j < batchnumvertices;j++)
9949                         {
9950                                 // if the wavefunc depends on time, evaluate it per-vertex
9951                                 if (waveparms[3])
9952                                 {
9953                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9954                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9955                                 }
9956                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9957                         }
9958                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9959                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9960                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9961                         {
9962 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9963 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9964 //                              rsurface.batchsvector3f_bufferoffset = 0;
9965 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9966 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9967 //                              rsurface.batchtvector3f_bufferoffset = 0;
9968                                 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);
9969                         }
9970                         break;
9971                 case Q3DEFORM_BULGE:
9972                         // deform vertex array to make the surface have moving bulges
9973 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9974 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9975 //                      rsurface.batchvertex3f_bufferoffset = 0;
9976 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9977 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9978 //                      rsurface.batchnormal3f_bufferoffset = 0;
9979                         for (j = 0;j < batchnumvertices;j++)
9980                         {
9981                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9982                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9983                         }
9984                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9985                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9986                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9987                         {
9988 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9989 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9990 //                              rsurface.batchsvector3f_bufferoffset = 0;
9991 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9992 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9993 //                              rsurface.batchtvector3f_bufferoffset = 0;
9994                                 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);
9995                         }
9996                         break;
9997                 case Q3DEFORM_MOVE:
9998                         // deform vertex array
9999                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10000                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10001                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10002                         VectorScale(deform->parms, scale, waveparms);
10003 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10004 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10005 //                      rsurface.batchvertex3f_bufferoffset = 0;
10006                         for (j = 0;j < batchnumvertices;j++)
10007                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10008                         break;
10009                 }
10010         }
10011
10012         // generate texcoords based on the chosen texcoord source
10013         switch(rsurface.texture->tcgen.tcgen)
10014         {
10015         default:
10016         case Q3TCGEN_TEXTURE:
10017                 break;
10018         case Q3TCGEN_LIGHTMAP:
10019 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10020 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10021 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10022                 if (rsurface.batchtexcoordlightmap2f)
10023                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10024                 break;
10025         case Q3TCGEN_VECTOR:
10026 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10027 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10028 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10029                 for (j = 0;j < batchnumvertices;j++)
10030                 {
10031                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10032                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10033                 }
10034                 break;
10035         case Q3TCGEN_ENVIRONMENT:
10036                 // make environment reflections using a spheremap
10037                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10038                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10039                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10040                 for (j = 0;j < batchnumvertices;j++)
10041                 {
10042                         // identical to Q3A's method, but executed in worldspace so
10043                         // carried models can be shiny too
10044
10045                         float viewer[3], d, reflected[3], worldreflected[3];
10046
10047                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10048                         // VectorNormalize(viewer);
10049
10050                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10051
10052                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10053                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10054                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10055                         // note: this is proportinal to viewer, so we can normalize later
10056
10057                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10058                         VectorNormalize(worldreflected);
10059
10060                         // note: this sphere map only uses world x and z!
10061                         // so positive and negative y will LOOK THE SAME.
10062                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10063                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10064                 }
10065                 break;
10066         }
10067         // the only tcmod that needs software vertex processing is turbulent, so
10068         // check for it here and apply the changes if needed
10069         // and we only support that as the first one
10070         // (handling a mixture of turbulent and other tcmods would be problematic
10071         //  without punting it entirely to a software path)
10072         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10073         {
10074                 amplitude = rsurface.texture->tcmods[0].parms[1];
10075                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10076 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10077 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10078 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10079                 for (j = 0;j < batchnumvertices;j++)
10080                 {
10081                         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);
10082                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10083                 }
10084         }
10085
10086         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10087         {
10088                 // convert the modified arrays to vertex structs
10089 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10090 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10091 //              rsurface.batchvertexmesh_bufferoffset = 0;
10092                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10093                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10094                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10095                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10096                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10097                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10098                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10099                 {
10100                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10101                         {
10102                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10103                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10104                         }
10105                 }
10106                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10107                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10108                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10109                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10110                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10111                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10112                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10113                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10114                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10115                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10116                 {
10117                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10118                         {
10119                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10120                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10121                         }
10122                 }
10123         }
10124
10125         // upload buffer data for the dynamic batch
10126         if ((r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10127         {
10128                 if (rsurface.batchvertexmesh)
10129                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10130                 else
10131                 {
10132                         if (rsurface.batchvertex3f)
10133                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10134                         if (rsurface.batchsvector3f)
10135                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10136                         if (rsurface.batchtvector3f)
10137                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10138                         if (rsurface.batchnormal3f)
10139                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10140                         if (rsurface.batchlightmapcolor4f)
10141                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10142                         if (rsurface.batchtexcoordtexture2f)
10143                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10144                         if (rsurface.batchtexcoordlightmap2f)
10145                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10146                         if (rsurface.batchskeletalindex4ub)
10147                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10148                         if (rsurface.batchskeletalweight4ub)
10149                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10150                 }
10151                 if (rsurface.batchelement3s)
10152                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10153                 else if (rsurface.batchelement3i)
10154                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10155         }
10156 }
10157
10158 void RSurf_DrawBatch(void)
10159 {
10160         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10161         // through the pipeline, killing it earlier in the pipeline would have
10162         // per-surface overhead rather than per-batch overhead, so it's best to
10163         // reject it here, before it hits glDraw.
10164         if (rsurface.batchnumtriangles == 0)
10165                 return;
10166 #if 0
10167         // batch debugging code
10168         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10169         {
10170                 int i;
10171                 int j;
10172                 int c;
10173                 const int *e;
10174                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10175                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10176                 {
10177                         c = e[i];
10178                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10179                         {
10180                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10181                                 {
10182                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10183                                                 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);
10184                                         break;
10185                                 }
10186                         }
10187                 }
10188         }
10189 #endif
10190         if (rsurface.batchmultidraw)
10191         {
10192                 // issue multiple draws rather than copying index data
10193                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10194                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10195                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10196                 for (i = 0;i < numsurfaces;)
10197                 {
10198                         // combine consecutive surfaces as one draw
10199                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10200                                 if (surfacelist[j] != surfacelist[k] + 1)
10201                                         break;
10202                         firstvertex = surfacelist[i]->num_firstvertex;
10203                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10204                         firsttriangle = surfacelist[i]->num_firsttriangle;
10205                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10206                         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);
10207                         i = j;
10208                 }
10209         }
10210         else
10211         {
10212                 // there is only one consecutive run of index data (may have been combined)
10213                 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);
10214         }
10215 }
10216
10217 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10218 {
10219         // pick the closest matching water plane
10220         int planeindex, vertexindex, bestplaneindex = -1;
10221         float d, bestd;
10222         vec3_t vert;
10223         const float *v;
10224         r_waterstate_waterplane_t *p;
10225         qboolean prepared = false;
10226         bestd = 0;
10227         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10228         {
10229                 if(p->camera_entity != rsurface.texture->camera_entity)
10230                         continue;
10231                 d = 0;
10232                 if(!prepared)
10233                 {
10234                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10235                         prepared = true;
10236                         if(rsurface.batchnumvertices == 0)
10237                                 break;
10238                 }
10239                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10240                 {
10241                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10242                         d += fabs(PlaneDiff(vert, &p->plane));
10243                 }
10244                 if (bestd > d || bestplaneindex < 0)
10245                 {
10246                         bestd = d;
10247                         bestplaneindex = planeindex;
10248                 }
10249         }
10250         return bestplaneindex;
10251         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10252         // this situation though, as it might be better to render single larger
10253         // batches with useless stuff (backface culled for example) than to
10254         // render multiple smaller batches
10255 }
10256
10257 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10258 {
10259         int i;
10260         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10261         rsurface.passcolor4f_vertexbuffer = 0;
10262         rsurface.passcolor4f_bufferoffset = 0;
10263         for (i = 0;i < rsurface.batchnumvertices;i++)
10264                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10265 }
10266
10267 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10268 {
10269         int i;
10270         float f;
10271         const float *v;
10272         const float *c;
10273         float *c2;
10274         if (rsurface.passcolor4f)
10275         {
10276                 // generate color arrays
10277                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10278                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10279                 rsurface.passcolor4f_vertexbuffer = 0;
10280                 rsurface.passcolor4f_bufferoffset = 0;
10281                 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)
10282                 {
10283                         f = RSurf_FogVertex(v);
10284                         c2[0] = c[0] * f;
10285                         c2[1] = c[1] * f;
10286                         c2[2] = c[2] * f;
10287                         c2[3] = c[3];
10288                 }
10289         }
10290         else
10291         {
10292                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10293                 rsurface.passcolor4f_vertexbuffer = 0;
10294                 rsurface.passcolor4f_bufferoffset = 0;
10295                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10296                 {
10297                         f = RSurf_FogVertex(v);
10298                         c2[0] = f;
10299                         c2[1] = f;
10300                         c2[2] = f;
10301                         c2[3] = 1;
10302                 }
10303         }
10304 }
10305
10306 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10307 {
10308         int i;
10309         float f;
10310         const float *v;
10311         const float *c;
10312         float *c2;
10313         if (!rsurface.passcolor4f)
10314                 return;
10315         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10316         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10317         rsurface.passcolor4f_vertexbuffer = 0;
10318         rsurface.passcolor4f_bufferoffset = 0;
10319         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)
10320         {
10321                 f = RSurf_FogVertex(v);
10322                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10323                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10324                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10325                 c2[3] = c[3];
10326         }
10327 }
10328
10329 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10330 {
10331         int i;
10332         const float *c;
10333         float *c2;
10334         if (!rsurface.passcolor4f)
10335                 return;
10336         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10337         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10338         rsurface.passcolor4f_vertexbuffer = 0;
10339         rsurface.passcolor4f_bufferoffset = 0;
10340         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10341         {
10342                 c2[0] = c[0] * r;
10343                 c2[1] = c[1] * g;
10344                 c2[2] = c[2] * b;
10345                 c2[3] = c[3] * a;
10346         }
10347 }
10348
10349 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10350 {
10351         int i;
10352         const float *c;
10353         float *c2;
10354         if (!rsurface.passcolor4f)
10355                 return;
10356         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10357         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10358         rsurface.passcolor4f_vertexbuffer = 0;
10359         rsurface.passcolor4f_bufferoffset = 0;
10360         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10361         {
10362                 c2[0] = c[0] + r_refdef.scene.ambient;
10363                 c2[1] = c[1] + r_refdef.scene.ambient;
10364                 c2[2] = c[2] + r_refdef.scene.ambient;
10365                 c2[3] = c[3];
10366         }
10367 }
10368
10369 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10370 {
10371         // TODO: optimize
10372         rsurface.passcolor4f = NULL;
10373         rsurface.passcolor4f_vertexbuffer = 0;
10374         rsurface.passcolor4f_bufferoffset = 0;
10375         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10376         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10377         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10378         GL_Color(r, g, b, a);
10379         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10380         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10381         R_Mesh_TexMatrix(0, NULL);
10382         RSurf_DrawBatch();
10383 }
10384
10385 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10386 {
10387         // TODO: optimize applyfog && applycolor case
10388         // just apply fog if necessary, and tint the fog color array if necessary
10389         rsurface.passcolor4f = NULL;
10390         rsurface.passcolor4f_vertexbuffer = 0;
10391         rsurface.passcolor4f_bufferoffset = 0;
10392         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10393         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10394         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10395         GL_Color(r, g, b, a);
10396         RSurf_DrawBatch();
10397 }
10398
10399 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10400 {
10401         // TODO: optimize
10402         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10403         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10404         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10405         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10406         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10407         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10408         GL_Color(r, g, b, a);
10409         RSurf_DrawBatch();
10410 }
10411
10412 static void RSurf_DrawBatch_GL11_ClampColor(void)
10413 {
10414         int i;
10415         const float *c1;
10416         float *c2;
10417         if (!rsurface.passcolor4f)
10418                 return;
10419         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10420         {
10421                 c2[0] = bound(0.0f, c1[0], 1.0f);
10422                 c2[1] = bound(0.0f, c1[1], 1.0f);
10423                 c2[2] = bound(0.0f, c1[2], 1.0f);
10424                 c2[3] = bound(0.0f, c1[3], 1.0f);
10425         }
10426 }
10427
10428 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10429 {
10430         int i;
10431         float f;
10432         const float *v;
10433         const float *n;
10434         float *c;
10435         //vec3_t eyedir;
10436
10437         // fake shading
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, 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)
10442         {
10443                 f = -DotProduct(r_refdef.view.forward, n);
10444                 f = max(0, f);
10445                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10446                 f *= r_refdef.lightmapintensity;
10447                 Vector4Set(c, f, f, f, 1);
10448         }
10449 }
10450
10451 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10452 {
10453         RSurf_DrawBatch_GL11_ApplyFakeLight();
10454         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10455         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10456         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10457         GL_Color(r, g, b, a);
10458         RSurf_DrawBatch();
10459 }
10460
10461 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10462 {
10463         int i;
10464         float f;
10465         float alpha;
10466         const float *v;
10467         const float *n;
10468         float *c;
10469         vec3_t ambientcolor;
10470         vec3_t diffusecolor;
10471         vec3_t lightdir;
10472         // TODO: optimize
10473         // model lighting
10474         VectorCopy(rsurface.modellight_lightdir, lightdir);
10475         f = 0.5f * r_refdef.lightmapintensity;
10476         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10477         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10478         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10479         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10480         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10481         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10482         alpha = *a;
10483         if (VectorLength2(diffusecolor) > 0)
10484         {
10485                 // q3-style directional shading
10486                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10487                 rsurface.passcolor4f_vertexbuffer = 0;
10488                 rsurface.passcolor4f_bufferoffset = 0;
10489                 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)
10490                 {
10491                         if ((f = DotProduct(n, lightdir)) > 0)
10492                                 VectorMA(ambientcolor, f, diffusecolor, c);
10493                         else
10494                                 VectorCopy(ambientcolor, c);
10495                         c[3] = alpha;
10496                 }
10497                 *r = 1;
10498                 *g = 1;
10499                 *b = 1;
10500                 *a = 1;
10501                 *applycolor = false;
10502         }
10503         else
10504         {
10505                 *r = ambientcolor[0];
10506                 *g = ambientcolor[1];
10507                 *b = ambientcolor[2];
10508                 rsurface.passcolor4f = NULL;
10509                 rsurface.passcolor4f_vertexbuffer = 0;
10510                 rsurface.passcolor4f_bufferoffset = 0;
10511         }
10512 }
10513
10514 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10515 {
10516         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10517         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10518         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10519         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10520         GL_Color(r, g, b, a);
10521         RSurf_DrawBatch();
10522 }
10523
10524 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10525 {
10526         int i;
10527         float f;
10528         const float *v;
10529         float *c;
10530
10531         // fake shading
10532         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10533         rsurface.passcolor4f_vertexbuffer = 0;
10534         rsurface.passcolor4f_bufferoffset = 0;
10535
10536         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10537         {
10538                 f = 1 - RSurf_FogVertex(v);
10539                 c[0] = r;
10540                 c[1] = g;
10541                 c[2] = b;
10542                 c[3] = f * a;
10543         }
10544 }
10545
10546 void RSurf_SetupDepthAndCulling(void)
10547 {
10548         // submodels are biased to avoid z-fighting with world surfaces that they
10549         // may be exactly overlapping (avoids z-fighting artifacts on certain
10550         // doors and things in Quake maps)
10551         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10552         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10553         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10554         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10555 }
10556
10557 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10558 {
10559         // transparent sky would be ridiculous
10560         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10561                 return;
10562         R_SetupShader_Generic_NoTexture(false, false);
10563         skyrenderlater = true;
10564         RSurf_SetupDepthAndCulling();
10565         GL_DepthMask(true);
10566         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10567         // skymasking on them, and Quake3 never did sky masking (unlike
10568         // software Quake and software Quake2), so disable the sky masking
10569         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10570         // and skymasking also looks very bad when noclipping outside the
10571         // level, so don't use it then either.
10572         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10573         {
10574                 R_Mesh_ResetTextureState();
10575                 if (skyrendermasked)
10576                 {
10577                         R_SetupShader_DepthOrShadow(false, false, false);
10578                         // depth-only (masking)
10579                         GL_ColorMask(0,0,0,0);
10580                         // just to make sure that braindead drivers don't draw
10581                         // anything despite that colormask...
10582                         GL_BlendFunc(GL_ZERO, GL_ONE);
10583                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10584                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10585                 }
10586                 else
10587                 {
10588                         R_SetupShader_Generic_NoTexture(false, false);
10589                         // fog sky
10590                         GL_BlendFunc(GL_ONE, GL_ZERO);
10591                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10592                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10593                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10594                 }
10595                 RSurf_DrawBatch();
10596                 if (skyrendermasked)
10597                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10598         }
10599         R_Mesh_ResetTextureState();
10600         GL_Color(1, 1, 1, 1);
10601 }
10602
10603 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10604 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10605 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10606 {
10607         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10608                 return;
10609         if (prepass)
10610         {
10611                 // render screenspace normalmap to texture
10612                 GL_DepthMask(true);
10613                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10614                 RSurf_DrawBatch();
10615                 return;
10616         }
10617
10618         // bind lightmap texture
10619
10620         // water/refraction/reflection/camera surfaces have to be handled specially
10621         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10622         {
10623                 int start, end, startplaneindex;
10624                 for (start = 0;start < texturenumsurfaces;start = end)
10625                 {
10626                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10627                         if(startplaneindex < 0)
10628                         {
10629                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10630                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10631                                 end = start + 1;
10632                                 continue;
10633                         }
10634                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10635                                 ;
10636                         // now that we have a batch using the same planeindex, render it
10637                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10638                         {
10639                                 // render water or distortion background
10640                                 GL_DepthMask(true);
10641                                 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);
10642                                 RSurf_DrawBatch();
10643                                 // blend surface on top
10644                                 GL_DepthMask(false);
10645                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10646                                 RSurf_DrawBatch();
10647                         }
10648                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10649                         {
10650                                 // render surface with reflection texture as input
10651                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10652                                 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);
10653                                 RSurf_DrawBatch();
10654                         }
10655                 }
10656                 return;
10657         }
10658
10659         // render surface batch normally
10660         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10661         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);
10662         RSurf_DrawBatch();
10663 }
10664
10665 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10666 {
10667         // OpenGL 1.3 path - anything not completely ancient
10668         qboolean applycolor;
10669         qboolean applyfog;
10670         int layerindex;
10671         const texturelayer_t *layer;
10672         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);
10673         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10674
10675         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10676         {
10677                 vec4_t layercolor;
10678                 int layertexrgbscale;
10679                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10680                 {
10681                         if (layerindex == 0)
10682                                 GL_AlphaTest(true);
10683                         else
10684                         {
10685                                 GL_AlphaTest(false);
10686                                 GL_DepthFunc(GL_EQUAL);
10687                         }
10688                 }
10689                 GL_DepthMask(layer->depthmask && writedepth);
10690                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10691                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10692                 {
10693                         layertexrgbscale = 4;
10694                         VectorScale(layer->color, 0.25f, layercolor);
10695                 }
10696                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10697                 {
10698                         layertexrgbscale = 2;
10699                         VectorScale(layer->color, 0.5f, layercolor);
10700                 }
10701                 else
10702                 {
10703                         layertexrgbscale = 1;
10704                         VectorScale(layer->color, 1.0f, layercolor);
10705                 }
10706                 layercolor[3] = layer->color[3];
10707                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10708                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10709                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10710                 switch (layer->type)
10711                 {
10712                 case TEXTURELAYERTYPE_LITTEXTURE:
10713                         // single-pass lightmapped texture with 2x rgbscale
10714                         R_Mesh_TexBind(0, r_texture_white);
10715                         R_Mesh_TexMatrix(0, NULL);
10716                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10717                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10718                         R_Mesh_TexBind(1, layer->texture);
10719                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10720                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10721                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10722                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10723                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10724                         else if (FAKELIGHT_ENABLED)
10725                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10726                         else if (rsurface.uselightmaptexture)
10727                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10728                         else
10729                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10730                         break;
10731                 case TEXTURELAYERTYPE_TEXTURE:
10732                         // singletexture unlit texture with transparency support
10733                         R_Mesh_TexBind(0, layer->texture);
10734                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10735                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10736                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10737                         R_Mesh_TexBind(1, 0);
10738                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10739                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10740                         break;
10741                 case TEXTURELAYERTYPE_FOG:
10742                         // singletexture fogging
10743                         if (layer->texture)
10744                         {
10745                                 R_Mesh_TexBind(0, layer->texture);
10746                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10747                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10748                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10749                         }
10750                         else
10751                         {
10752                                 R_Mesh_TexBind(0, 0);
10753                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10754                         }
10755                         R_Mesh_TexBind(1, 0);
10756                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10757                         // generate a color array for the fog pass
10758                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10759                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10760                         RSurf_DrawBatch();
10761                         break;
10762                 default:
10763                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10764                 }
10765         }
10766         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10767         {
10768                 GL_DepthFunc(GL_LEQUAL);
10769                 GL_AlphaTest(false);
10770         }
10771 }
10772
10773 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10774 {
10775         // OpenGL 1.1 - crusty old voodoo path
10776         qboolean applyfog;
10777         int layerindex;
10778         const texturelayer_t *layer;
10779         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);
10780         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10781
10782         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10783         {
10784                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10785                 {
10786                         if (layerindex == 0)
10787                                 GL_AlphaTest(true);
10788                         else
10789                         {
10790                                 GL_AlphaTest(false);
10791                                 GL_DepthFunc(GL_EQUAL);
10792                         }
10793                 }
10794                 GL_DepthMask(layer->depthmask && writedepth);
10795                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10796                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10797                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10798                 switch (layer->type)
10799                 {
10800                 case TEXTURELAYERTYPE_LITTEXTURE:
10801                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10802                         {
10803                                 // two-pass lit texture with 2x rgbscale
10804                                 // first the lightmap pass
10805                                 R_Mesh_TexBind(0, r_texture_white);
10806                                 R_Mesh_TexMatrix(0, NULL);
10807                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10808                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10809                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10810                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10811                                 else if (FAKELIGHT_ENABLED)
10812                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10813                                 else if (rsurface.uselightmaptexture)
10814                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10815                                 else
10816                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10817                                 // then apply the texture to it
10818                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10819                                 R_Mesh_TexBind(0, layer->texture);
10820                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10821                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10822                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10823                                 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);
10824                         }
10825                         else
10826                         {
10827                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10828                                 R_Mesh_TexBind(0, layer->texture);
10829                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10830                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10831                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10832                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10833                                         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);
10834                                 else if (FAKELIGHT_ENABLED)
10835                                         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);
10836                                 else
10837                                         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);
10838                         }
10839                         break;
10840                 case TEXTURELAYERTYPE_TEXTURE:
10841                         // singletexture unlit texture with transparency support
10842                         R_Mesh_TexBind(0, layer->texture);
10843                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10844                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10845                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10846                         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);
10847                         break;
10848                 case TEXTURELAYERTYPE_FOG:
10849                         // singletexture fogging
10850                         if (layer->texture)
10851                         {
10852                                 R_Mesh_TexBind(0, layer->texture);
10853                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10854                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10855                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10856                         }
10857                         else
10858                         {
10859                                 R_Mesh_TexBind(0, 0);
10860                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10861                         }
10862                         // generate a color array for the fog pass
10863                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10864                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10865                         RSurf_DrawBatch();
10866                         break;
10867                 default:
10868                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10869                 }
10870         }
10871         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10872         {
10873                 GL_DepthFunc(GL_LEQUAL);
10874                 GL_AlphaTest(false);
10875         }
10876 }
10877
10878 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10879 {
10880         int vi;
10881         int j;
10882         r_vertexgeneric_t *batchvertex;
10883         float c[4];
10884
10885 //      R_Mesh_ResetTextureState();
10886         R_SetupShader_Generic_NoTexture(false, false);
10887
10888         if(rsurface.texture && rsurface.texture->currentskinframe)
10889         {
10890                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10891                 c[3] *= rsurface.texture->currentalpha;
10892         }
10893         else
10894         {
10895                 c[0] = 1;
10896                 c[1] = 0;
10897                 c[2] = 1;
10898                 c[3] = 1;
10899         }
10900
10901         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10902         {
10903                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10904                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10905                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10906         }
10907
10908         // brighten it up (as texture value 127 means "unlit")
10909         c[0] *= 2 * r_refdef.view.colorscale;
10910         c[1] *= 2 * r_refdef.view.colorscale;
10911         c[2] *= 2 * r_refdef.view.colorscale;
10912
10913         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10914                 c[3] *= r_wateralpha.value;
10915
10916         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10917         {
10918                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10919                 GL_DepthMask(false);
10920         }
10921         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10922         {
10923                 GL_BlendFunc(GL_ONE, GL_ONE);
10924                 GL_DepthMask(false);
10925         }
10926         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10927         {
10928                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10929                 GL_DepthMask(false);
10930         }
10931         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10932         {
10933                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10934                 GL_DepthMask(false);
10935         }
10936         else
10937         {
10938                 GL_BlendFunc(GL_ONE, GL_ZERO);
10939                 GL_DepthMask(writedepth);
10940         }
10941
10942         if (r_showsurfaces.integer == 3)
10943         {
10944                 rsurface.passcolor4f = NULL;
10945
10946                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10947                 {
10948                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10949
10950                         rsurface.passcolor4f = NULL;
10951                         rsurface.passcolor4f_vertexbuffer = 0;
10952                         rsurface.passcolor4f_bufferoffset = 0;
10953                 }
10954                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10955                 {
10956                         qboolean applycolor = true;
10957                         float one = 1.0;
10958
10959                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10960
10961                         r_refdef.lightmapintensity = 1;
10962                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10963                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10964                 }
10965                 else if (FAKELIGHT_ENABLED)
10966                 {
10967                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10968
10969                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10970                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10971                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10972                 }
10973                 else
10974                 {
10975                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10976
10977                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10978                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10979                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10980                 }
10981
10982                 if(!rsurface.passcolor4f)
10983                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10984
10985                 RSurf_DrawBatch_GL11_ApplyAmbient();
10986                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10987                 if(r_refdef.fogenabled)
10988                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10989                 RSurf_DrawBatch_GL11_ClampColor();
10990
10991                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10992                 R_SetupShader_Generic_NoTexture(false, false);
10993                 RSurf_DrawBatch();
10994         }
10995         else if (!r_refdef.view.showdebug)
10996         {
10997                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10998                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10999                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11000                 {
11001                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11002                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11003                 }
11004                 R_Mesh_PrepareVertices_Generic_Unlock();
11005                 RSurf_DrawBatch();
11006         }
11007         else if (r_showsurfaces.integer == 4)
11008         {
11009                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11010                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11011                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11012                 {
11013                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11014                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11015                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11016                 }
11017                 R_Mesh_PrepareVertices_Generic_Unlock();
11018                 RSurf_DrawBatch();
11019         }
11020         else if (r_showsurfaces.integer == 2)
11021         {
11022                 const int *e;
11023                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11024                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11025                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11026                 {
11027                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11028                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11029                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11030                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11031                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11032                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11033                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11034                 }
11035                 R_Mesh_PrepareVertices_Generic_Unlock();
11036                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11037         }
11038         else
11039         {
11040                 int texturesurfaceindex;
11041                 int k;
11042                 const msurface_t *surface;
11043                 float surfacecolor4f[4];
11044                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11045                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11046                 vi = 0;
11047                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11048                 {
11049                         surface = texturesurfacelist[texturesurfaceindex];
11050                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11051                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11052                         for (j = 0;j < surface->num_vertices;j++)
11053                         {
11054                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11055                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11056                                 vi++;
11057                         }
11058                 }
11059                 R_Mesh_PrepareVertices_Generic_Unlock();
11060                 RSurf_DrawBatch();
11061         }
11062 }
11063
11064 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11065 {
11066         CHECKGLERROR
11067         RSurf_SetupDepthAndCulling();
11068         if (r_showsurfaces.integer)
11069         {
11070                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11071                 return;
11072         }
11073         switch (vid.renderpath)
11074         {
11075         case RENDERPATH_GL20:
11076         case RENDERPATH_D3D9:
11077         case RENDERPATH_D3D10:
11078         case RENDERPATH_D3D11:
11079         case RENDERPATH_SOFT:
11080         case RENDERPATH_GLES2:
11081                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11082                 break;
11083         case RENDERPATH_GL13:
11084         case RENDERPATH_GLES1:
11085                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11086                 break;
11087         case RENDERPATH_GL11:
11088                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11089                 break;
11090         }
11091         CHECKGLERROR
11092 }
11093
11094 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11095 {
11096         CHECKGLERROR
11097         RSurf_SetupDepthAndCulling();
11098         if (r_showsurfaces.integer)
11099         {
11100                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11101                 return;
11102         }
11103         switch (vid.renderpath)
11104         {
11105         case RENDERPATH_GL20:
11106         case RENDERPATH_D3D9:
11107         case RENDERPATH_D3D10:
11108         case RENDERPATH_D3D11:
11109         case RENDERPATH_SOFT:
11110         case RENDERPATH_GLES2:
11111                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11112                 break;
11113         case RENDERPATH_GL13:
11114         case RENDERPATH_GLES1:
11115                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11116                 break;
11117         case RENDERPATH_GL11:
11118                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11119                 break;
11120         }
11121         CHECKGLERROR
11122 }
11123
11124 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11125 {
11126         int i, j;
11127         int texturenumsurfaces, endsurface;
11128         texture_t *texture;
11129         const msurface_t *surface;
11130         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11131
11132         // if the model is static it doesn't matter what value we give for
11133         // wantnormals and wanttangents, so this logic uses only rules applicable
11134         // to a model, knowing that they are meaningless otherwise
11135         if (ent == r_refdef.scene.worldentity)
11136                 RSurf_ActiveWorldEntity();
11137         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11138                 RSurf_ActiveModelEntity(ent, false, false, false);
11139         else
11140         {
11141                 switch (vid.renderpath)
11142                 {
11143                 case RENDERPATH_GL20:
11144                 case RENDERPATH_D3D9:
11145                 case RENDERPATH_D3D10:
11146                 case RENDERPATH_D3D11:
11147                 case RENDERPATH_SOFT:
11148                 case RENDERPATH_GLES2:
11149                         RSurf_ActiveModelEntity(ent, true, true, false);
11150                         break;
11151                 case RENDERPATH_GL11:
11152                 case RENDERPATH_GL13:
11153                 case RENDERPATH_GLES1:
11154                         RSurf_ActiveModelEntity(ent, true, false, false);
11155                         break;
11156                 }
11157         }
11158
11159         if (r_transparentdepthmasking.integer)
11160         {
11161                 qboolean setup = false;
11162                 for (i = 0;i < numsurfaces;i = j)
11163                 {
11164                         j = i + 1;
11165                         surface = rsurface.modelsurfaces + surfacelist[i];
11166                         texture = surface->texture;
11167                         rsurface.texture = R_GetCurrentTexture(texture);
11168                         rsurface.lightmaptexture = NULL;
11169                         rsurface.deluxemaptexture = NULL;
11170                         rsurface.uselightmaptexture = false;
11171                         // scan ahead until we find a different texture
11172                         endsurface = min(i + 1024, numsurfaces);
11173                         texturenumsurfaces = 0;
11174                         texturesurfacelist[texturenumsurfaces++] = surface;
11175                         for (;j < endsurface;j++)
11176                         {
11177                                 surface = rsurface.modelsurfaces + surfacelist[j];
11178                                 if (texture != surface->texture)
11179                                         break;
11180                                 texturesurfacelist[texturenumsurfaces++] = surface;
11181                         }
11182                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11183                                 continue;
11184                         // render the range of surfaces as depth
11185                         if (!setup)
11186                         {
11187                                 setup = true;
11188                                 GL_ColorMask(0,0,0,0);
11189                                 GL_Color(1,1,1,1);
11190                                 GL_DepthTest(true);
11191                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11192                                 GL_DepthMask(true);
11193 //                              R_Mesh_ResetTextureState();
11194                         }
11195                         RSurf_SetupDepthAndCulling();
11196                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11197                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11198                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11199                         RSurf_DrawBatch();
11200                 }
11201                 if (setup)
11202                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11203         }
11204
11205         for (i = 0;i < numsurfaces;i = j)
11206         {
11207                 j = i + 1;
11208                 surface = rsurface.modelsurfaces + surfacelist[i];
11209                 texture = surface->texture;
11210                 rsurface.texture = R_GetCurrentTexture(texture);
11211                 // scan ahead until we find a different texture
11212                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11213                 texturenumsurfaces = 0;
11214                 texturesurfacelist[texturenumsurfaces++] = surface;
11215                 if(FAKELIGHT_ENABLED)
11216                 {
11217                         rsurface.lightmaptexture = NULL;
11218                         rsurface.deluxemaptexture = NULL;
11219                         rsurface.uselightmaptexture = false;
11220                         for (;j < endsurface;j++)
11221                         {
11222                                 surface = rsurface.modelsurfaces + surfacelist[j];
11223                                 if (texture != surface->texture)
11224                                         break;
11225                                 texturesurfacelist[texturenumsurfaces++] = surface;
11226                         }
11227                 }
11228                 else
11229                 {
11230                         rsurface.lightmaptexture = surface->lightmaptexture;
11231                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11232                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11233                         for (;j < endsurface;j++)
11234                         {
11235                                 surface = rsurface.modelsurfaces + surfacelist[j];
11236                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11237                                         break;
11238                                 texturesurfacelist[texturenumsurfaces++] = surface;
11239                         }
11240                 }
11241                 // render the range of surfaces
11242                 if (ent == r_refdef.scene.worldentity)
11243                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11244                 else
11245                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11246         }
11247         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11248 }
11249
11250 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11251 {
11252         // transparent surfaces get pushed off into the transparent queue
11253         int surfacelistindex;
11254         const msurface_t *surface;
11255         vec3_t tempcenter, center;
11256         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11257         {
11258                 surface = texturesurfacelist[surfacelistindex];
11259                 if (r_transparent_sortsurfacesbynearest.integer)
11260                 {
11261                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11262                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11263                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11264                 }
11265                 else
11266                 {
11267                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11268                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11269                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11270                 }
11271                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11272                 if (rsurface.entity->transparent_offset) // transparent offset
11273                 {
11274                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11275                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11276                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11277                 }
11278                 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);
11279         }
11280 }
11281
11282 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11283 {
11284         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11285                 return;
11286         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11287                 return;
11288         RSurf_SetupDepthAndCulling();
11289         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11290         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11291         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11292         RSurf_DrawBatch();
11293 }
11294
11295 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11296 {
11297         CHECKGLERROR
11298         if (depthonly)
11299                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11300         else if (prepass)
11301         {
11302                 if (!rsurface.texture->currentnumlayers)
11303                         return;
11304                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11305                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11306                 else
11307                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11308         }
11309         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11310                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11311         else if (!rsurface.texture->currentnumlayers)
11312                 return;
11313         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11314         {
11315                 // in the deferred case, transparent surfaces were queued during prepass
11316                 if (!r_shadow_usingdeferredprepass)
11317                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11318         }
11319         else
11320         {
11321                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11322                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11323         }
11324         CHECKGLERROR
11325 }
11326
11327 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11328 {
11329         int i, j;
11330         texture_t *texture;
11331         R_FrameData_SetMark();
11332         // break the surface list down into batches by texture and use of lightmapping
11333         for (i = 0;i < numsurfaces;i = j)
11334         {
11335                 j = i + 1;
11336                 // texture is the base texture pointer, rsurface.texture is the
11337                 // current frame/skin the texture is directing us to use (for example
11338                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11339                 // use skin 1 instead)
11340                 texture = surfacelist[i]->texture;
11341                 rsurface.texture = R_GetCurrentTexture(texture);
11342                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11343                 {
11344                         // if this texture is not the kind we want, skip ahead to the next one
11345                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11346                                 ;
11347                         continue;
11348                 }
11349                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11350                 {
11351                         rsurface.lightmaptexture = NULL;
11352                         rsurface.deluxemaptexture = NULL;
11353                         rsurface.uselightmaptexture = false;
11354                         // simply scan ahead until we find a different texture or lightmap state
11355                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11356                                 ;
11357                 }
11358                 else
11359                 {
11360                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11361                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11362                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11363                         // simply scan ahead until we find a different texture or lightmap state
11364                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11365                                 ;
11366                 }
11367                 // render the range of surfaces
11368                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11369         }
11370         R_FrameData_ReturnToMark();
11371 }
11372
11373 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11374 {
11375         CHECKGLERROR
11376         if (depthonly)
11377                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11378         else if (prepass)
11379         {
11380                 if (!rsurface.texture->currentnumlayers)
11381                         return;
11382                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11383                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11384                 else
11385                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11386         }
11387         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11388                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11389         else if (!rsurface.texture->currentnumlayers)
11390                 return;
11391         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11392         {
11393                 // in the deferred case, transparent surfaces were queued during prepass
11394                 if (!r_shadow_usingdeferredprepass)
11395                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11396         }
11397         else
11398         {
11399                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11400                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11401         }
11402         CHECKGLERROR
11403 }
11404
11405 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11406 {
11407         int i, j;
11408         texture_t *texture;
11409         R_FrameData_SetMark();
11410         // break the surface list down into batches by texture and use of lightmapping
11411         for (i = 0;i < numsurfaces;i = j)
11412         {
11413                 j = i + 1;
11414                 // texture is the base texture pointer, rsurface.texture is the
11415                 // current frame/skin the texture is directing us to use (for example
11416                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11417                 // use skin 1 instead)
11418                 texture = surfacelist[i]->texture;
11419                 rsurface.texture = R_GetCurrentTexture(texture);
11420                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11421                 {
11422                         // if this texture is not the kind we want, skip ahead to the next one
11423                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11424                                 ;
11425                         continue;
11426                 }
11427                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11428                 {
11429                         rsurface.lightmaptexture = NULL;
11430                         rsurface.deluxemaptexture = NULL;
11431                         rsurface.uselightmaptexture = false;
11432                         // simply scan ahead until we find a different texture or lightmap state
11433                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11434                                 ;
11435                 }
11436                 else
11437                 {
11438                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11439                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11440                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11441                         // simply scan ahead until we find a different texture or lightmap state
11442                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11443                                 ;
11444                 }
11445                 // render the range of surfaces
11446                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11447         }
11448         R_FrameData_ReturnToMark();
11449 }
11450
11451 float locboxvertex3f[6*4*3] =
11452 {
11453         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11454         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11455         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11456         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11457         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11458         1,0,0, 0,0,0, 0,1,0, 1,1,0
11459 };
11460
11461 unsigned short locboxelements[6*2*3] =
11462 {
11463          0, 1, 2, 0, 2, 3,
11464          4, 5, 6, 4, 6, 7,
11465          8, 9,10, 8,10,11,
11466         12,13,14, 12,14,15,
11467         16,17,18, 16,18,19,
11468         20,21,22, 20,22,23
11469 };
11470
11471 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11472 {
11473         int i, j;
11474         cl_locnode_t *loc = (cl_locnode_t *)ent;
11475         vec3_t mins, size;
11476         float vertex3f[6*4*3];
11477         CHECKGLERROR
11478         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11479         GL_DepthMask(false);
11480         GL_DepthRange(0, 1);
11481         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11482         GL_DepthTest(true);
11483         GL_CullFace(GL_NONE);
11484         R_EntityMatrix(&identitymatrix);
11485
11486 //      R_Mesh_ResetTextureState();
11487
11488         i = surfacelist[0];
11489         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11490                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11491                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11492                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11493
11494         if (VectorCompare(loc->mins, loc->maxs))
11495         {
11496                 VectorSet(size, 2, 2, 2);
11497                 VectorMA(loc->mins, -0.5f, size, mins);
11498         }
11499         else
11500         {
11501                 VectorCopy(loc->mins, mins);
11502                 VectorSubtract(loc->maxs, loc->mins, size);
11503         }
11504
11505         for (i = 0;i < 6*4*3;)
11506                 for (j = 0;j < 3;j++, i++)
11507                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11508
11509         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11510         R_SetupShader_Generic_NoTexture(false, false);
11511         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11512 }
11513
11514 void R_DrawLocs(void)
11515 {
11516         int index;
11517         cl_locnode_t *loc, *nearestloc;
11518         vec3_t center;
11519         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11520         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11521         {
11522                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11523                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11524         }
11525 }
11526
11527 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11528 {
11529         if (decalsystem->decals)
11530                 Mem_Free(decalsystem->decals);
11531         memset(decalsystem, 0, sizeof(*decalsystem));
11532 }
11533
11534 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)
11535 {
11536         tridecal_t *decal;
11537         tridecal_t *decals;
11538         int i;
11539
11540         // expand or initialize the system
11541         if (decalsystem->maxdecals <= decalsystem->numdecals)
11542         {
11543                 decalsystem_t old = *decalsystem;
11544                 qboolean useshortelements;
11545                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11546                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11547                 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)));
11548                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11549                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11550                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11551                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11552                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11553                 if (decalsystem->numdecals)
11554                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11555                 if (old.decals)
11556                         Mem_Free(old.decals);
11557                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11558                         decalsystem->element3i[i] = i;
11559                 if (useshortelements)
11560                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11561                                 decalsystem->element3s[i] = i;
11562         }
11563
11564         // grab a decal and search for another free slot for the next one
11565         decals = decalsystem->decals;
11566         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11567         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11568                 ;
11569         decalsystem->freedecal = i;
11570         if (decalsystem->numdecals <= i)
11571                 decalsystem->numdecals = i + 1;
11572
11573         // initialize the decal
11574         decal->lived = 0;
11575         decal->triangleindex = triangleindex;
11576         decal->surfaceindex = surfaceindex;
11577         decal->decalsequence = decalsequence;
11578         decal->color4f[0][0] = c0[0];
11579         decal->color4f[0][1] = c0[1];
11580         decal->color4f[0][2] = c0[2];
11581         decal->color4f[0][3] = 1;
11582         decal->color4f[1][0] = c1[0];
11583         decal->color4f[1][1] = c1[1];
11584         decal->color4f[1][2] = c1[2];
11585         decal->color4f[1][3] = 1;
11586         decal->color4f[2][0] = c2[0];
11587         decal->color4f[2][1] = c2[1];
11588         decal->color4f[2][2] = c2[2];
11589         decal->color4f[2][3] = 1;
11590         decal->vertex3f[0][0] = v0[0];
11591         decal->vertex3f[0][1] = v0[1];
11592         decal->vertex3f[0][2] = v0[2];
11593         decal->vertex3f[1][0] = v1[0];
11594         decal->vertex3f[1][1] = v1[1];
11595         decal->vertex3f[1][2] = v1[2];
11596         decal->vertex3f[2][0] = v2[0];
11597         decal->vertex3f[2][1] = v2[1];
11598         decal->vertex3f[2][2] = v2[2];
11599         decal->texcoord2f[0][0] = t0[0];
11600         decal->texcoord2f[0][1] = t0[1];
11601         decal->texcoord2f[1][0] = t1[0];
11602         decal->texcoord2f[1][1] = t1[1];
11603         decal->texcoord2f[2][0] = t2[0];
11604         decal->texcoord2f[2][1] = t2[1];
11605         TriangleNormal(v0, v1, v2, decal->plane);
11606         VectorNormalize(decal->plane);
11607         decal->plane[3] = DotProduct(v0, decal->plane);
11608 }
11609
11610 extern cvar_t cl_decals_bias;
11611 extern cvar_t cl_decals_models;
11612 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11613 // baseparms, parms, temps
11614 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)
11615 {
11616         int cornerindex;
11617         int index;
11618         float v[9][3];
11619         const float *vertex3f;
11620         const float *normal3f;
11621         int numpoints;
11622         float points[2][9][3];
11623         float temp[3];
11624         float tc[9][2];
11625         float f;
11626         float c[9][4];
11627         const int *e;
11628
11629         e = rsurface.modelelement3i + 3*triangleindex;
11630
11631         vertex3f = rsurface.modelvertex3f;
11632         normal3f = rsurface.modelnormal3f;
11633
11634         if (normal3f)
11635         {
11636                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11637                 {
11638                         index = 3*e[cornerindex];
11639                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11640                 }
11641         }
11642         else
11643         {
11644                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11645                 {
11646                         index = 3*e[cornerindex];
11647                         VectorCopy(vertex3f + index, v[cornerindex]);
11648                 }
11649         }
11650
11651         // cull backfaces
11652         //TriangleNormal(v[0], v[1], v[2], normal);
11653         //if (DotProduct(normal, localnormal) < 0.0f)
11654         //      continue;
11655         // clip by each of the box planes formed from the projection matrix
11656         // if anything survives, we emit the decal
11657         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]);
11658         if (numpoints < 3)
11659                 return;
11660         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]);
11661         if (numpoints < 3)
11662                 return;
11663         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]);
11664         if (numpoints < 3)
11665                 return;
11666         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]);
11667         if (numpoints < 3)
11668                 return;
11669         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]);
11670         if (numpoints < 3)
11671                 return;
11672         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]);
11673         if (numpoints < 3)
11674                 return;
11675         // some part of the triangle survived, so we have to accept it...
11676         if (dynamic)
11677         {
11678                 // dynamic always uses the original triangle
11679                 numpoints = 3;
11680                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11681                 {
11682                         index = 3*e[cornerindex];
11683                         VectorCopy(vertex3f + index, v[cornerindex]);
11684                 }
11685         }
11686         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11687         {
11688                 // convert vertex positions to texcoords
11689                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11690                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11691                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11692                 // calculate distance fade from the projection origin
11693                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11694                 f = bound(0.0f, f, 1.0f);
11695                 c[cornerindex][0] = r * f;
11696                 c[cornerindex][1] = g * f;
11697                 c[cornerindex][2] = b * f;
11698                 c[cornerindex][3] = 1.0f;
11699                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11700         }
11701         if (dynamic)
11702                 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);
11703         else
11704                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11705                         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);
11706 }
11707 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)
11708 {
11709         matrix4x4_t projection;
11710         decalsystem_t *decalsystem;
11711         qboolean dynamic;
11712         dp_model_t *model;
11713         const msurface_t *surface;
11714         const msurface_t *surfaces;
11715         const int *surfacelist;
11716         const texture_t *texture;
11717         int numtriangles;
11718         int numsurfacelist;
11719         int surfacelistindex;
11720         int surfaceindex;
11721         int triangleindex;
11722         float localorigin[3];
11723         float localnormal[3];
11724         float localmins[3];
11725         float localmaxs[3];
11726         float localsize;
11727         //float normal[3];
11728         float planes[6][4];
11729         float angles[3];
11730         bih_t *bih;
11731         int bih_triangles_count;
11732         int bih_triangles[256];
11733         int bih_surfaces[256];
11734
11735         decalsystem = &ent->decalsystem;
11736         model = ent->model;
11737         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11738         {
11739                 R_DecalSystem_Reset(&ent->decalsystem);
11740                 return;
11741         }
11742
11743         if (!model->brush.data_leafs && !cl_decals_models.integer)
11744         {
11745                 if (decalsystem->model)
11746                         R_DecalSystem_Reset(decalsystem);
11747                 return;
11748         }
11749
11750         if (decalsystem->model != model)
11751                 R_DecalSystem_Reset(decalsystem);
11752         decalsystem->model = model;
11753
11754         RSurf_ActiveModelEntity(ent, true, false, false);
11755
11756         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11757         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11758         VectorNormalize(localnormal);
11759         localsize = worldsize*rsurface.inversematrixscale;
11760         localmins[0] = localorigin[0] - localsize;
11761         localmins[1] = localorigin[1] - localsize;
11762         localmins[2] = localorigin[2] - localsize;
11763         localmaxs[0] = localorigin[0] + localsize;
11764         localmaxs[1] = localorigin[1] + localsize;
11765         localmaxs[2] = localorigin[2] + localsize;
11766
11767         //VectorCopy(localnormal, planes[4]);
11768         //VectorVectors(planes[4], planes[2], planes[0]);
11769         AnglesFromVectors(angles, localnormal, NULL, false);
11770         AngleVectors(angles, planes[0], planes[2], planes[4]);
11771         VectorNegate(planes[0], planes[1]);
11772         VectorNegate(planes[2], planes[3]);
11773         VectorNegate(planes[4], planes[5]);
11774         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11775         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11776         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11777         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11778         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11779         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11780
11781 #if 1
11782 // works
11783 {
11784         matrix4x4_t forwardprojection;
11785         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11786         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11787 }
11788 #else
11789 // broken
11790 {
11791         float projectionvector[4][3];
11792         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11793         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11794         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11795         projectionvector[0][0] = planes[0][0] * ilocalsize;
11796         projectionvector[0][1] = planes[1][0] * ilocalsize;
11797         projectionvector[0][2] = planes[2][0] * ilocalsize;
11798         projectionvector[1][0] = planes[0][1] * ilocalsize;
11799         projectionvector[1][1] = planes[1][1] * ilocalsize;
11800         projectionvector[1][2] = planes[2][1] * ilocalsize;
11801         projectionvector[2][0] = planes[0][2] * ilocalsize;
11802         projectionvector[2][1] = planes[1][2] * ilocalsize;
11803         projectionvector[2][2] = planes[2][2] * ilocalsize;
11804         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11805         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11806         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11807         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11808 }
11809 #endif
11810
11811         dynamic = model->surfmesh.isanimated;
11812         numsurfacelist = model->nummodelsurfaces;
11813         surfacelist = model->sortedmodelsurfaces;
11814         surfaces = model->data_surfaces;
11815
11816         bih = NULL;
11817         bih_triangles_count = -1;
11818         if(!dynamic)
11819         {
11820                 if(model->render_bih.numleafs)
11821                         bih = &model->render_bih;
11822                 else if(model->collision_bih.numleafs)
11823                         bih = &model->collision_bih;
11824         }
11825         if(bih)
11826                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11827         if(bih_triangles_count == 0)
11828                 return;
11829         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11830                 return;
11831         if(bih_triangles_count > 0)
11832         {
11833                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11834                 {
11835                         surfaceindex = bih_surfaces[triangleindex];
11836                         surface = surfaces + surfaceindex;
11837                         texture = surface->texture;
11838                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11839                                 continue;
11840                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11841                                 continue;
11842                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11843                 }
11844         }
11845         else
11846         {
11847                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11848                 {
11849                         surfaceindex = surfacelist[surfacelistindex];
11850                         surface = surfaces + surfaceindex;
11851                         // check cull box first because it rejects more than any other check
11852                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11853                                 continue;
11854                         // skip transparent surfaces
11855                         texture = surface->texture;
11856                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11857                                 continue;
11858                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11859                                 continue;
11860                         numtriangles = surface->num_triangles;
11861                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11862                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11863                 }
11864         }
11865 }
11866
11867 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11868 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)
11869 {
11870         int renderentityindex;
11871         float worldmins[3];
11872         float worldmaxs[3];
11873         entity_render_t *ent;
11874
11875         if (!cl_decals_newsystem.integer)
11876                 return;
11877
11878         worldmins[0] = worldorigin[0] - worldsize;
11879         worldmins[1] = worldorigin[1] - worldsize;
11880         worldmins[2] = worldorigin[2] - worldsize;
11881         worldmaxs[0] = worldorigin[0] + worldsize;
11882         worldmaxs[1] = worldorigin[1] + worldsize;
11883         worldmaxs[2] = worldorigin[2] + worldsize;
11884
11885         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11886
11887         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11888         {
11889                 ent = r_refdef.scene.entities[renderentityindex];
11890                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11891                         continue;
11892
11893                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11894         }
11895 }
11896
11897 typedef struct r_decalsystem_splatqueue_s
11898 {
11899         vec3_t worldorigin;
11900         vec3_t worldnormal;
11901         float color[4];
11902         float tcrange[4];
11903         float worldsize;
11904         int decalsequence;
11905 }
11906 r_decalsystem_splatqueue_t;
11907
11908 int r_decalsystem_numqueued = 0;
11909 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11910
11911 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)
11912 {
11913         r_decalsystem_splatqueue_t *queue;
11914
11915         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11916                 return;
11917
11918         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11919         VectorCopy(worldorigin, queue->worldorigin);
11920         VectorCopy(worldnormal, queue->worldnormal);
11921         Vector4Set(queue->color, r, g, b, a);
11922         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11923         queue->worldsize = worldsize;
11924         queue->decalsequence = cl.decalsequence++;
11925 }
11926
11927 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11928 {
11929         int i;
11930         r_decalsystem_splatqueue_t *queue;
11931
11932         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11933                 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);
11934         r_decalsystem_numqueued = 0;
11935 }
11936
11937 extern cvar_t cl_decals_max;
11938 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11939 {
11940         int i;
11941         decalsystem_t *decalsystem = &ent->decalsystem;
11942         int numdecals;
11943         int killsequence;
11944         tridecal_t *decal;
11945         float frametime;
11946         float lifetime;
11947
11948         if (!decalsystem->numdecals)
11949                 return;
11950
11951         if (r_showsurfaces.integer)
11952                 return;
11953
11954         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11955         {
11956                 R_DecalSystem_Reset(decalsystem);
11957                 return;
11958         }
11959
11960         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11961         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11962
11963         if (decalsystem->lastupdatetime)
11964                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11965         else
11966                 frametime = 0;
11967         decalsystem->lastupdatetime = r_refdef.scene.time;
11968         numdecals = decalsystem->numdecals;
11969
11970         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11971         {
11972                 if (decal->color4f[0][3])
11973                 {
11974                         decal->lived += frametime;
11975                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11976                         {
11977                                 memset(decal, 0, sizeof(*decal));
11978                                 if (decalsystem->freedecal > i)
11979                                         decalsystem->freedecal = i;
11980                         }
11981                 }
11982         }
11983         decal = decalsystem->decals;
11984         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11985                 numdecals--;
11986
11987         // collapse the array by shuffling the tail decals into the gaps
11988         for (;;)
11989         {
11990                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11991                         decalsystem->freedecal++;
11992                 if (decalsystem->freedecal == numdecals)
11993                         break;
11994                 decal[decalsystem->freedecal] = decal[--numdecals];
11995         }
11996
11997         decalsystem->numdecals = numdecals;
11998
11999         if (numdecals <= 0)
12000         {
12001                 // if there are no decals left, reset decalsystem
12002                 R_DecalSystem_Reset(decalsystem);
12003         }
12004 }
12005
12006 extern skinframe_t *decalskinframe;
12007 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12008 {
12009         int i;
12010         decalsystem_t *decalsystem = &ent->decalsystem;
12011         int numdecals;
12012         tridecal_t *decal;
12013         float faderate;
12014         float alpha;
12015         float *v3f;
12016         float *c4f;
12017         float *t2f;
12018         const int *e;
12019         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12020         int numtris = 0;
12021
12022         numdecals = decalsystem->numdecals;
12023         if (!numdecals)
12024                 return;
12025
12026         if (r_showsurfaces.integer)
12027                 return;
12028
12029         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12030         {
12031                 R_DecalSystem_Reset(decalsystem);
12032                 return;
12033         }
12034
12035         // if the model is static it doesn't matter what value we give for
12036         // wantnormals and wanttangents, so this logic uses only rules applicable
12037         // to a model, knowing that they are meaningless otherwise
12038         if (ent == r_refdef.scene.worldentity)
12039                 RSurf_ActiveWorldEntity();
12040         else
12041                 RSurf_ActiveModelEntity(ent, false, false, false);
12042
12043         decalsystem->lastupdatetime = r_refdef.scene.time;
12044
12045         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12046
12047         // update vertex positions for animated models
12048         v3f = decalsystem->vertex3f;
12049         c4f = decalsystem->color4f;
12050         t2f = decalsystem->texcoord2f;
12051         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12052         {
12053                 if (!decal->color4f[0][3])
12054                         continue;
12055
12056                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12057                         continue;
12058
12059                 // skip backfaces
12060                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12061                         continue;
12062
12063                 // update color values for fading decals
12064                 if (decal->lived >= cl_decals_time.value)
12065                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12066                 else
12067                         alpha = 1.0f;
12068
12069                 c4f[ 0] = decal->color4f[0][0] * alpha;
12070                 c4f[ 1] = decal->color4f[0][1] * alpha;
12071                 c4f[ 2] = decal->color4f[0][2] * alpha;
12072                 c4f[ 3] = 1;
12073                 c4f[ 4] = decal->color4f[1][0] * alpha;
12074                 c4f[ 5] = decal->color4f[1][1] * alpha;
12075                 c4f[ 6] = decal->color4f[1][2] * alpha;
12076                 c4f[ 7] = 1;
12077                 c4f[ 8] = decal->color4f[2][0] * alpha;
12078                 c4f[ 9] = decal->color4f[2][1] * alpha;
12079                 c4f[10] = decal->color4f[2][2] * alpha;
12080                 c4f[11] = 1;
12081
12082                 t2f[0] = decal->texcoord2f[0][0];
12083                 t2f[1] = decal->texcoord2f[0][1];
12084                 t2f[2] = decal->texcoord2f[1][0];
12085                 t2f[3] = decal->texcoord2f[1][1];
12086                 t2f[4] = decal->texcoord2f[2][0];
12087                 t2f[5] = decal->texcoord2f[2][1];
12088
12089                 // update vertex positions for animated models
12090                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12091                 {
12092                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12093                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12094                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12095                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12096                 }
12097                 else
12098                 {
12099                         VectorCopy(decal->vertex3f[0], v3f);
12100                         VectorCopy(decal->vertex3f[1], v3f + 3);
12101                         VectorCopy(decal->vertex3f[2], v3f + 6);
12102                 }
12103
12104                 if (r_refdef.fogenabled)
12105                 {
12106                         alpha = RSurf_FogVertex(v3f);
12107                         VectorScale(c4f, alpha, c4f);
12108                         alpha = RSurf_FogVertex(v3f + 3);
12109                         VectorScale(c4f + 4, alpha, c4f + 4);
12110                         alpha = RSurf_FogVertex(v3f + 6);
12111                         VectorScale(c4f + 8, alpha, c4f + 8);
12112                 }
12113
12114                 v3f += 9;
12115                 c4f += 12;
12116                 t2f += 6;
12117                 numtris++;
12118         }
12119
12120         if (numtris > 0)
12121         {
12122                 r_refdef.stats[r_stat_drawndecals] += numtris;
12123
12124                 // now render the decals all at once
12125                 // (this assumes they all use one particle font texture!)
12126                 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);
12127 //              R_Mesh_ResetTextureState();
12128                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12129                 GL_DepthMask(false);
12130                 GL_DepthRange(0, 1);
12131                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12132                 GL_DepthTest(true);
12133                 GL_CullFace(GL_NONE);
12134                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12135                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12136                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12137         }
12138 }
12139
12140 static void R_DrawModelDecals(void)
12141 {
12142         int i, numdecals;
12143
12144         // fade faster when there are too many decals
12145         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12146         for (i = 0;i < r_refdef.scene.numentities;i++)
12147                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12148
12149         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12150         for (i = 0;i < r_refdef.scene.numentities;i++)
12151                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12152                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12153
12154         R_DecalSystem_ApplySplatEntitiesQueue();
12155
12156         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12157         for (i = 0;i < r_refdef.scene.numentities;i++)
12158                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12159
12160         r_refdef.stats[r_stat_totaldecals] += numdecals;
12161
12162         if (r_showsurfaces.integer)
12163                 return;
12164
12165         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12166
12167         for (i = 0;i < r_refdef.scene.numentities;i++)
12168         {
12169                 if (!r_refdef.viewcache.entityvisible[i])
12170                         continue;
12171                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12172                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12173         }
12174 }
12175
12176 extern cvar_t mod_collision_bih;
12177 static void R_DrawDebugModel(void)
12178 {
12179         entity_render_t *ent = rsurface.entity;
12180         int i, j, k, l, flagsmask;
12181         const msurface_t *surface;
12182         dp_model_t *model = ent->model;
12183         vec3_t v;
12184
12185         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12186                 return;
12187
12188         if (r_showoverdraw.value > 0)
12189         {
12190                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12191                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12192                 R_SetupShader_Generic_NoTexture(false, false);
12193                 GL_DepthTest(false);
12194                 GL_DepthMask(false);
12195                 GL_DepthRange(0, 1);
12196                 GL_BlendFunc(GL_ONE, GL_ONE);
12197                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12198                 {
12199                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12200                                 continue;
12201                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12202                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12203                         {
12204                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12205                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12206                                 if (!rsurface.texture->currentlayers->depthmask)
12207                                         GL_Color(c, 0, 0, 1.0f);
12208                                 else if (ent == r_refdef.scene.worldentity)
12209                                         GL_Color(c, c, c, 1.0f);
12210                                 else
12211                                         GL_Color(0, c, 0, 1.0f);
12212                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12213                                 RSurf_DrawBatch();
12214                         }
12215                 }
12216                 rsurface.texture = NULL;
12217         }
12218
12219         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12220
12221 //      R_Mesh_ResetTextureState();
12222         R_SetupShader_Generic_NoTexture(false, false);
12223         GL_DepthRange(0, 1);
12224         GL_DepthTest(!r_showdisabledepthtest.integer);
12225         GL_DepthMask(false);
12226         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12227
12228         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12229         {
12230                 int triangleindex;
12231                 int bihleafindex;
12232                 qboolean cullbox = false;
12233                 const q3mbrush_t *brush;
12234                 const bih_t *bih = &model->collision_bih;
12235                 const bih_leaf_t *bihleaf;
12236                 float vertex3f[3][3];
12237                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12238                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12239                 {
12240                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12241                                 continue;
12242                         switch (bihleaf->type)
12243                         {
12244                         case BIH_BRUSH:
12245                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12246                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12247                                 {
12248                                         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);
12249                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12250                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12251                                 }
12252                                 break;
12253                         case BIH_COLLISIONTRIANGLE:
12254                                 triangleindex = bihleaf->itemindex;
12255                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12256                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12257                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12258                                 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);
12259                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12260                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12261                                 break;
12262                         case BIH_RENDERTRIANGLE:
12263                                 triangleindex = bihleaf->itemindex;
12264                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12265                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12266                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12267                                 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);
12268                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12269                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12270                                 break;
12271                         }
12272                 }
12273         }
12274
12275         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12276
12277 #ifndef USE_GLES2
12278         if (r_showtris.integer && qglPolygonMode)
12279         {
12280                 if (r_showdisabledepthtest.integer)
12281                 {
12282                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12283                         GL_DepthMask(false);
12284                 }
12285                 else
12286                 {
12287                         GL_BlendFunc(GL_ONE, GL_ZERO);
12288                         GL_DepthMask(true);
12289                 }
12290                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12291                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12292                 {
12293                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12294                                 continue;
12295                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12296                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12297                         {
12298                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12299                                 if (!rsurface.texture->currentlayers->depthmask)
12300                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12301                                 else if (ent == r_refdef.scene.worldentity)
12302                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12303                                 else
12304                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12305                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12306                                 RSurf_DrawBatch();
12307                         }
12308                 }
12309                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12310                 rsurface.texture = NULL;
12311         }
12312
12313         if (r_shownormals.value != 0 && qglBegin)
12314         {
12315                 if (r_showdisabledepthtest.integer)
12316                 {
12317                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12318                         GL_DepthMask(false);
12319                 }
12320                 else
12321                 {
12322                         GL_BlendFunc(GL_ONE, GL_ZERO);
12323                         GL_DepthMask(true);
12324                 }
12325                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12326                 {
12327                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12328                                 continue;
12329                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12330                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12331                         {
12332                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12333                                 qglBegin(GL_LINES);
12334                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12335                                 {
12336                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12337                                         {
12338                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12339                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12340                                                 qglVertex3f(v[0], v[1], v[2]);
12341                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12342                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12343                                                 qglVertex3f(v[0], v[1], v[2]);
12344                                         }
12345                                 }
12346                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12347                                 {
12348                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12349                                         {
12350                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12351                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12352                                                 qglVertex3f(v[0], v[1], v[2]);
12353                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12354                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12355                                                 qglVertex3f(v[0], v[1], v[2]);
12356                                         }
12357                                 }
12358                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12359                                 {
12360                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12361                                         {
12362                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12363                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12364                                                 qglVertex3f(v[0], v[1], v[2]);
12365                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12366                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12367                                                 qglVertex3f(v[0], v[1], v[2]);
12368                                         }
12369                                 }
12370                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12371                                 {
12372                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12373                                         {
12374                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12375                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12376                                                 qglVertex3f(v[0], v[1], v[2]);
12377                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12378                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12379                                                 qglVertex3f(v[0], v[1], v[2]);
12380                                         }
12381                                 }
12382                                 qglEnd();
12383                                 CHECKGLERROR
12384                         }
12385                 }
12386                 rsurface.texture = NULL;
12387         }
12388 #endif
12389 }
12390
12391 int r_maxsurfacelist = 0;
12392 const msurface_t **r_surfacelist = NULL;
12393 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12394 {
12395         int i, j, endj, flagsmask;
12396         dp_model_t *model = r_refdef.scene.worldmodel;
12397         msurface_t *surfaces;
12398         unsigned char *update;
12399         int numsurfacelist = 0;
12400         if (model == NULL)
12401                 return;
12402
12403         if (r_maxsurfacelist < model->num_surfaces)
12404         {
12405                 r_maxsurfacelist = model->num_surfaces;
12406                 if (r_surfacelist)
12407                         Mem_Free((msurface_t**)r_surfacelist);
12408                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12409         }
12410
12411         RSurf_ActiveWorldEntity();
12412
12413         surfaces = model->data_surfaces;
12414         update = model->brushq1.lightmapupdateflags;
12415
12416         // update light styles on this submodel
12417         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12418         {
12419                 model_brush_lightstyleinfo_t *style;
12420                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12421                 {
12422                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12423                         {
12424                                 int *list = style->surfacelist;
12425                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12426                                 for (j = 0;j < style->numsurfaces;j++)
12427                                         update[list[j]] = true;
12428                         }
12429                 }
12430         }
12431
12432         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12433
12434         if (debug)
12435         {
12436                 R_DrawDebugModel();
12437                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12438                 return;
12439         }
12440
12441         rsurface.lightmaptexture = NULL;
12442         rsurface.deluxemaptexture = NULL;
12443         rsurface.uselightmaptexture = false;
12444         rsurface.texture = NULL;
12445         rsurface.rtlight = NULL;
12446         numsurfacelist = 0;
12447         // add visible surfaces to draw list
12448         for (i = 0;i < model->nummodelsurfaces;i++)
12449         {
12450                 j = model->sortedmodelsurfaces[i];
12451                 if (r_refdef.viewcache.world_surfacevisible[j])
12452                         r_surfacelist[numsurfacelist++] = surfaces + j;
12453         }
12454         // update lightmaps if needed
12455         if (model->brushq1.firstrender)
12456         {
12457                 model->brushq1.firstrender = false;
12458                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12459                         if (update[j])
12460                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12461         }
12462         else if (update)
12463         {
12464                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12465                         if (r_refdef.viewcache.world_surfacevisible[j])
12466                                 if (update[j])
12467                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12468         }
12469         // don't do anything if there were no surfaces
12470         if (!numsurfacelist)
12471         {
12472                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12473                 return;
12474         }
12475         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12476
12477         // add to stats if desired
12478         if (r_speeds.integer && !skysurfaces && !depthonly)
12479         {
12480                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12481                 for (j = 0;j < numsurfacelist;j++)
12482                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12483         }
12484
12485         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12486 }
12487
12488 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12489 {
12490         int i, j, endj, flagsmask;
12491         dp_model_t *model = ent->model;
12492         msurface_t *surfaces;
12493         unsigned char *update;
12494         int numsurfacelist = 0;
12495         if (model == NULL)
12496                 return;
12497
12498         if (r_maxsurfacelist < model->num_surfaces)
12499         {
12500                 r_maxsurfacelist = model->num_surfaces;
12501                 if (r_surfacelist)
12502                         Mem_Free((msurface_t **)r_surfacelist);
12503                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12504         }
12505
12506         // if the model is static it doesn't matter what value we give for
12507         // wantnormals and wanttangents, so this logic uses only rules applicable
12508         // to a model, knowing that they are meaningless otherwise
12509         if (ent == r_refdef.scene.worldentity)
12510                 RSurf_ActiveWorldEntity();
12511         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12512                 RSurf_ActiveModelEntity(ent, false, false, false);
12513         else if (prepass)
12514                 RSurf_ActiveModelEntity(ent, true, true, true);
12515         else if (depthonly)
12516         {
12517                 switch (vid.renderpath)
12518                 {
12519                 case RENDERPATH_GL20:
12520                 case RENDERPATH_D3D9:
12521                 case RENDERPATH_D3D10:
12522                 case RENDERPATH_D3D11:
12523                 case RENDERPATH_SOFT:
12524                 case RENDERPATH_GLES2:
12525                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12526                         break;
12527                 case RENDERPATH_GL11:
12528                 case RENDERPATH_GL13:
12529                 case RENDERPATH_GLES1:
12530                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12531                         break;
12532                 }
12533         }
12534         else
12535         {
12536                 switch (vid.renderpath)
12537                 {
12538                 case RENDERPATH_GL20:
12539                 case RENDERPATH_D3D9:
12540                 case RENDERPATH_D3D10:
12541                 case RENDERPATH_D3D11:
12542                 case RENDERPATH_SOFT:
12543                 case RENDERPATH_GLES2:
12544                         RSurf_ActiveModelEntity(ent, true, true, false);
12545                         break;
12546                 case RENDERPATH_GL11:
12547                 case RENDERPATH_GL13:
12548                 case RENDERPATH_GLES1:
12549                         RSurf_ActiveModelEntity(ent, true, false, false);
12550                         break;
12551                 }
12552         }
12553
12554         surfaces = model->data_surfaces;
12555         update = model->brushq1.lightmapupdateflags;
12556
12557         // update light styles
12558         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12559         {
12560                 model_brush_lightstyleinfo_t *style;
12561                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12562                 {
12563                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12564                         {
12565                                 int *list = style->surfacelist;
12566                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12567                                 for (j = 0;j < style->numsurfaces;j++)
12568                                         update[list[j]] = true;
12569                         }
12570                 }
12571         }
12572
12573         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12574
12575         if (debug)
12576         {
12577                 R_DrawDebugModel();
12578                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12579                 return;
12580         }
12581
12582         rsurface.lightmaptexture = NULL;
12583         rsurface.deluxemaptexture = NULL;
12584         rsurface.uselightmaptexture = false;
12585         rsurface.texture = NULL;
12586         rsurface.rtlight = NULL;
12587         numsurfacelist = 0;
12588         // add visible surfaces to draw list
12589         for (i = 0;i < model->nummodelsurfaces;i++)
12590                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12591         // don't do anything if there were no surfaces
12592         if (!numsurfacelist)
12593         {
12594                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12595                 return;
12596         }
12597         // update lightmaps if needed
12598         if (update)
12599         {
12600                 int updated = 0;
12601                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12602                 {
12603                         if (update[j])
12604                         {
12605                                 updated++;
12606                                 R_BuildLightMap(ent, surfaces + j);
12607                         }
12608                 }
12609         }
12610
12611         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12612
12613         // add to stats if desired
12614         if (r_speeds.integer && !skysurfaces && !depthonly)
12615         {
12616                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12617                 for (j = 0;j < numsurfacelist;j++)
12618                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12619         }
12620
12621         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12622 }
12623
12624 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12625 {
12626         static texture_t texture;
12627         static msurface_t surface;
12628         const msurface_t *surfacelist = &surface;
12629
12630         // fake enough texture and surface state to render this geometry
12631
12632         texture.update_lastrenderframe = -1; // regenerate this texture
12633         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12634         texture.currentskinframe = skinframe;
12635         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12636         texture.offsetmapping = OFFSETMAPPING_OFF;
12637         texture.offsetscale = 1;
12638         texture.specularscalemod = 1;
12639         texture.specularpowermod = 1;
12640         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12641         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12642         // JUST GREP FOR "specularscalemod = 1".
12643
12644         surface.texture = &texture;
12645         surface.num_triangles = numtriangles;
12646         surface.num_firsttriangle = firsttriangle;
12647         surface.num_vertices = numvertices;
12648         surface.num_firstvertex = firstvertex;
12649
12650         // now render it
12651         rsurface.texture = R_GetCurrentTexture(surface.texture);
12652         rsurface.lightmaptexture = NULL;
12653         rsurface.deluxemaptexture = NULL;
12654         rsurface.uselightmaptexture = false;
12655         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12656 }
12657
12658 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)
12659 {
12660         static msurface_t surface;
12661         const msurface_t *surfacelist = &surface;
12662
12663         // fake enough texture and surface state to render this geometry
12664         surface.texture = texture;
12665         surface.num_triangles = numtriangles;
12666         surface.num_firsttriangle = firsttriangle;
12667         surface.num_vertices = numvertices;
12668         surface.num_firstvertex = firstvertex;
12669
12670         // now render it
12671         rsurface.texture = R_GetCurrentTexture(surface.texture);
12672         rsurface.lightmaptexture = NULL;
12673         rsurface.deluxemaptexture = NULL;
12674         rsurface.uselightmaptexture = false;
12675         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12676 }