]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
755925c9f993eb58409901c747a68fdcf1a187c7
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47 static qboolean r_gpuskeletal;
48
49 //
50 // screen size info
51 //
52 r_refdef_t r_refdef;
53
54 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
55 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
56 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
57 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
58 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
60 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
61 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
62 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
63 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
64 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
65 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
66
67 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
68 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
69 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
70 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
71 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
72
73 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
74 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
75 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
76 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
77 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
78 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
79 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
80 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
81 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
82 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
83 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
84 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
85 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
90 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
91 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
92 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
93 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
94 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
95 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
96 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
97 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
98 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
99 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
100 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
101 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
102 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
103 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
104 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
105 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
106 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
107 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
108
109 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
110 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
111 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
112
113 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
114 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
115 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
116 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
117 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
118 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
119 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
120 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
121 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
122 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
123 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
124 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
125 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
126 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
127 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
128 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
130 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
131 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
132 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
133 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
134 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
135 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
136 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
137 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
138 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
139
140 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
141 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
142 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
143 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
144 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
145 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
146 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
147 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
148
149 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
150 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
151
152 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
153 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
154 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
155
156 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
157 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
158 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
159 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
160 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
161 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
162 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
163 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
164 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
165
166 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
167 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
168 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
169 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
171 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
172 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
173 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
174 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
175 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
176 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
177 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
178 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
179 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
180 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
181 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
182 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
183 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
184 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
185
186 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
187 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
188 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
189 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
190 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
191 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
192 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
193 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
194 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
195
196 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
197 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
198 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
199 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
200
201 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
202 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
203
204 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
205 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
206 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
207 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
208 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
209 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
210
211 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
212 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
213 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
214 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
215 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
218 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
219 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
220 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
221
222 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
223
224 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
225
226 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
227
228 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
229
230 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
231 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
232 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
234
235 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
236 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
237
238 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
239
240 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
241 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
242 {
243         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
244         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
245         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
246         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
247 };
248
249 extern cvar_t v_glslgamma;
250 extern cvar_t v_glslgamma_2d;
251
252 extern qboolean v_flipped_state;
253
254 r_framebufferstate_t r_fb;
255
256 /// shadow volume bsp struct with automatically growing nodes buffer
257 svbsp_t r_svbsp;
258
259 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
260
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
274
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
277 {
278         char basename[64];
279         rtexture_t *texture;
280 }
281 cubemapinfo_t;
282
283 int r_texture_numcubemaps;
284 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
285
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
289
290 typedef struct r_qwskincache_s
291 {
292         char name[MAX_QPATH];
293         skinframe_t *skinframe;
294 }
295 r_qwskincache_t;
296
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
299
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
304 {
305         0, 0, 0,
306         1, 0, 0,
307         1, 1, 0,
308         0, 1, 0
309 };
310 const float r_d3dscreenvertex3f[12] =
311 {
312         0, 1, 0,
313         1, 1, 0,
314         1, 0, 0,
315         0, 0, 0
316 };
317
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
319 {
320         int i;
321         for (i = 0;i < verts;i++)
322         {
323                 out[0] = in[0] * r;
324                 out[1] = in[1] * g;
325                 out[2] = in[2] * b;
326                 out[3] = in[3];
327                 in += 4;
328                 out += 4;
329         }
330 }
331
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = r;
338                 out[1] = g;
339                 out[2] = b;
340                 out[3] = a;
341                 out += 4;
342         }
343 }
344
345 // FIXME: move this to client?
346 void FOG_clear(void)
347 {
348         if (gamemode == GAME_NEHAHRA)
349         {
350                 Cvar_Set("gl_fogenable", "0");
351                 Cvar_Set("gl_fogdensity", "0.2");
352                 Cvar_Set("gl_fogred", "0.3");
353                 Cvar_Set("gl_foggreen", "0.3");
354                 Cvar_Set("gl_fogblue", "0.3");
355         }
356         r_refdef.fog_density = 0;
357         r_refdef.fog_red = 0;
358         r_refdef.fog_green = 0;
359         r_refdef.fog_blue = 0;
360         r_refdef.fog_alpha = 1;
361         r_refdef.fog_start = 0;
362         r_refdef.fog_end = 16384;
363         r_refdef.fog_height = 1<<30;
364         r_refdef.fog_fadedepth = 128;
365         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
366 }
367
368 static void R_BuildBlankTextures(void)
369 {
370         unsigned char data[4];
371         data[2] = 128; // normal X
372         data[1] = 128; // normal Y
373         data[0] = 255; // normal Z
374         data[3] = 255; // height
375         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 255;
377         data[1] = 255;
378         data[2] = 255;
379         data[3] = 255;
380         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 128;
382         data[1] = 128;
383         data[2] = 128;
384         data[3] = 255;
385         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 0;
387         data[1] = 0;
388         data[2] = 0;
389         data[3] = 255;
390         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildNoTexture(void)
394 {
395         int x, y;
396         unsigned char pix[16][16][4];
397         // this makes a light grey/dark grey checkerboard texture
398         for (y = 0;y < 16;y++)
399         {
400                 for (x = 0;x < 16;x++)
401                 {
402                         if ((y < 8) ^ (x < 8))
403                         {
404                                 pix[y][x][0] = 128;
405                                 pix[y][x][1] = 128;
406                                 pix[y][x][2] = 128;
407                                 pix[y][x][3] = 255;
408                         }
409                         else
410                         {
411                                 pix[y][x][0] = 64;
412                                 pix[y][x][1] = 64;
413                                 pix[y][x][2] = 64;
414                                 pix[y][x][3] = 255;
415                         }
416                 }
417         }
418         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
419 }
420
421 static void R_BuildWhiteCube(void)
422 {
423         unsigned char data[6*1*1*4];
424         memset(data, 255, sizeof(data));
425         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
426 }
427
428 static void R_BuildNormalizationCube(void)
429 {
430         int x, y, side;
431         vec3_t v;
432         vec_t s, t, intensity;
433 #define NORMSIZE 64
434         unsigned char *data;
435         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436         for (side = 0;side < 6;side++)
437         {
438                 for (y = 0;y < NORMSIZE;y++)
439                 {
440                         for (x = 0;x < NORMSIZE;x++)
441                         {
442                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 switch(side)
445                                 {
446                                 default:
447                                 case 0:
448                                         v[0] = 1;
449                                         v[1] = -t;
450                                         v[2] = -s;
451                                         break;
452                                 case 1:
453                                         v[0] = -1;
454                                         v[1] = -t;
455                                         v[2] = s;
456                                         break;
457                                 case 2:
458                                         v[0] = s;
459                                         v[1] = 1;
460                                         v[2] = t;
461                                         break;
462                                 case 3:
463                                         v[0] = s;
464                                         v[1] = -1;
465                                         v[2] = -t;
466                                         break;
467                                 case 4:
468                                         v[0] = s;
469                                         v[1] = -t;
470                                         v[2] = 1;
471                                         break;
472                                 case 5:
473                                         v[0] = -s;
474                                         v[1] = -t;
475                                         v[2] = -1;
476                                         break;
477                                 }
478                                 intensity = 127.0f / sqrt(DotProduct(v, v));
479                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482                                 data[((side*64+y)*64+x)*4+3] = 255;
483                         }
484                 }
485         }
486         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
487         Mem_Free(data);
488 }
489
490 static void R_BuildFogTexture(void)
491 {
492         int x, b;
493 #define FOGWIDTH 256
494         unsigned char data1[FOGWIDTH][4];
495         //unsigned char data2[FOGWIDTH][4];
496         double d, r, alpha;
497
498         r_refdef.fogmasktable_start = r_refdef.fog_start;
499         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500         r_refdef.fogmasktable_range = r_refdef.fogrange;
501         r_refdef.fogmasktable_density = r_refdef.fog_density;
502
503         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505         {
506                 d = (x * r - r_refdef.fogmasktable_start);
507                 if(developer_extra.integer)
508                         Con_DPrintf("%f ", d);
509                 d = max(0, d);
510                 if (r_fog_exp2.integer)
511                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512                 else
513                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514                 if(developer_extra.integer)
515                         Con_DPrintf(" : %f ", alpha);
516                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517                 if(developer_extra.integer)
518                         Con_DPrintf(" = %f\n", alpha);
519                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
520         }
521
522         for (x = 0;x < FOGWIDTH;x++)
523         {
524                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
525                 data1[x][0] = b;
526                 data1[x][1] = b;
527                 data1[x][2] = b;
528                 data1[x][3] = 255;
529                 //data2[x][0] = 255 - b;
530                 //data2[x][1] = 255 - b;
531                 //data2[x][2] = 255 - b;
532                 //data2[x][3] = 255;
533         }
534         if (r_texture_fogattenuation)
535         {
536                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538         }
539         else
540         {
541                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
543         }
544 }
545
546 static void R_BuildFogHeightTexture(void)
547 {
548         unsigned char *inpixels;
549         int size;
550         int x;
551         int y;
552         int j;
553         float c[4];
554         float f;
555         inpixels = NULL;
556         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557         if (r_refdef.fogheighttexturename[0])
558                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
559         if (!inpixels)
560         {
561                 r_refdef.fog_height_tablesize = 0;
562                 if (r_texture_fogheighttexture)
563                         R_FreeTexture(r_texture_fogheighttexture);
564                 r_texture_fogheighttexture = NULL;
565                 if (r_refdef.fog_height_table2d)
566                         Mem_Free(r_refdef.fog_height_table2d);
567                 r_refdef.fog_height_table2d = NULL;
568                 if (r_refdef.fog_height_table1d)
569                         Mem_Free(r_refdef.fog_height_table1d);
570                 r_refdef.fog_height_table1d = NULL;
571                 return;
572         }
573         size = image_width;
574         r_refdef.fog_height_tablesize = size;
575         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578         Mem_Free(inpixels);
579         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
580         // average fog color table accounting for every fog layer between a point
581         // and the camera.  (Note: attenuation is handled separately!)
582         for (y = 0;y < size;y++)
583         {
584                 for (x = 0;x < size;x++)
585                 {
586                         Vector4Clear(c);
587                         f = 0;
588                         if (x < y)
589                         {
590                                 for (j = x;j <= y;j++)
591                                 {
592                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
593                                         f++;
594                                 }
595                         }
596                         else
597                         {
598                                 for (j = x;j >= y;j--)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         f = 1.0f / f;
605                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
609                 }
610         }
611         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
612 }
613
614 //=======================================================================================================================================================
615
616 static const char *builtinshaderstrings[] =
617 {
618 #include "shader_glsl.h"
619 0
620 };
621
622 const char *builtinhlslshaderstrings[] =
623 {
624 #include "shader_hlsl.h"
625 0
626 };
627
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
630
631 //=======================================================================================================================================================
632
633 typedef struct shaderpermutationinfo_s
634 {
635         const char *pretext;
636         const char *name;
637 }
638 shaderpermutationinfo_t;
639
640 typedef struct shadermodeinfo_s
641 {
642         const char *filename;
643         const char *pretext;
644         const char *name;
645 }
646 shadermodeinfo_t;
647
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {
651         {"#define USEDIFFUSE\n", " diffuse"},
652         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653         {"#define USEVIEWTINT\n", " viewtint"},
654         {"#define USECOLORMAPPING\n", " colormapping"},
655         {"#define USESATURATION\n", " saturation"},
656         {"#define USEFOGINSIDE\n", " foginside"},
657         {"#define USEFOGOUTSIDE\n", " fogoutside"},
658         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660         {"#define USEGAMMARAMPS\n", " gammaramps"},
661         {"#define USECUBEFILTER\n", " cubefilter"},
662         {"#define USEGLOW\n", " glow"},
663         {"#define USEBLOOM\n", " bloom"},
664         {"#define USESPECULAR\n", " specular"},
665         {"#define USEPOSTPROCESSING\n", " postprocessing"},
666         {"#define USEREFLECTION\n", " reflection"},
667         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
671         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673         {"#define USEALPHAKILL\n", " alphakill"},
674         {"#define USEREFLECTCUBE\n", " reflectcube"},
675         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676         {"#define USEBOUNCEGRID\n", " bouncegrid"},
677         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
678         {"#define USETRIPPY\n", " trippy"},
679         {"#define USEDEPTHRGB\n", " depthrgb"},
680         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
681         {"#define USESKELETAL\n", " skeletal"}
682 };
683
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
686 {
687         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
697         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
698         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
699         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
700         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
701         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
702         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
707 {
708         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
725 };
726
727 struct r_glsl_permutation_s;
728 typedef struct r_glsl_permutation_s
729 {
730         /// hash lookup data
731         struct r_glsl_permutation_s *hashnext;
732         unsigned int mode;
733         unsigned int permutation;
734
735         /// indicates if we have tried compiling this permutation already
736         qboolean compiled;
737         /// 0 if compilation failed
738         int program;
739         // texture units assigned to each detected uniform
740         int tex_Texture_First;
741         int tex_Texture_Second;
742         int tex_Texture_GammaRamps;
743         int tex_Texture_Normal;
744         int tex_Texture_Color;
745         int tex_Texture_Gloss;
746         int tex_Texture_Glow;
747         int tex_Texture_SecondaryNormal;
748         int tex_Texture_SecondaryColor;
749         int tex_Texture_SecondaryGloss;
750         int tex_Texture_SecondaryGlow;
751         int tex_Texture_Pants;
752         int tex_Texture_Shirt;
753         int tex_Texture_FogHeightTexture;
754         int tex_Texture_FogMask;
755         int tex_Texture_Lightmap;
756         int tex_Texture_Deluxemap;
757         int tex_Texture_Attenuation;
758         int tex_Texture_Cube;
759         int tex_Texture_Refraction;
760         int tex_Texture_Reflection;
761         int tex_Texture_ShadowMap2D;
762         int tex_Texture_CubeProjection;
763         int tex_Texture_ScreenNormalMap;
764         int tex_Texture_ScreenDiffuse;
765         int tex_Texture_ScreenSpecular;
766         int tex_Texture_ReflectMask;
767         int tex_Texture_ReflectCube;
768         int tex_Texture_BounceGrid;
769         /// locations of detected uniforms in program object, or -1 if not found
770         int loc_Texture_First;
771         int loc_Texture_Second;
772         int loc_Texture_GammaRamps;
773         int loc_Texture_Normal;
774         int loc_Texture_Color;
775         int loc_Texture_Gloss;
776         int loc_Texture_Glow;
777         int loc_Texture_SecondaryNormal;
778         int loc_Texture_SecondaryColor;
779         int loc_Texture_SecondaryGloss;
780         int loc_Texture_SecondaryGlow;
781         int loc_Texture_Pants;
782         int loc_Texture_Shirt;
783         int loc_Texture_FogHeightTexture;
784         int loc_Texture_FogMask;
785         int loc_Texture_Lightmap;
786         int loc_Texture_Deluxemap;
787         int loc_Texture_Attenuation;
788         int loc_Texture_Cube;
789         int loc_Texture_Refraction;
790         int loc_Texture_Reflection;
791         int loc_Texture_ShadowMap2D;
792         int loc_Texture_CubeProjection;
793         int loc_Texture_ScreenNormalMap;
794         int loc_Texture_ScreenDiffuse;
795         int loc_Texture_ScreenSpecular;
796         int loc_Texture_ReflectMask;
797         int loc_Texture_ReflectCube;
798         int loc_Texture_BounceGrid;
799         int loc_Alpha;
800         int loc_BloomBlur_Parameters;
801         int loc_ClientTime;
802         int loc_Color_Ambient;
803         int loc_Color_Diffuse;
804         int loc_Color_Specular;
805         int loc_Color_Glow;
806         int loc_Color_Pants;
807         int loc_Color_Shirt;
808         int loc_DeferredColor_Ambient;
809         int loc_DeferredColor_Diffuse;
810         int loc_DeferredColor_Specular;
811         int loc_DeferredMod_Diffuse;
812         int loc_DeferredMod_Specular;
813         int loc_DistortScaleRefractReflect;
814         int loc_EyePosition;
815         int loc_FogColor;
816         int loc_FogHeightFade;
817         int loc_FogPlane;
818         int loc_FogPlaneViewDist;
819         int loc_FogRangeRecip;
820         int loc_LightColor;
821         int loc_LightDir;
822         int loc_LightPosition;
823         int loc_OffsetMapping_ScaleSteps;
824         int loc_OffsetMapping_LodDistance;
825         int loc_OffsetMapping_Bias;
826         int loc_PixelSize;
827         int loc_ReflectColor;
828         int loc_ReflectFactor;
829         int loc_ReflectOffset;
830         int loc_RefractColor;
831         int loc_Saturation;
832         int loc_ScreenCenterRefractReflect;
833         int loc_ScreenScaleRefractReflect;
834         int loc_ScreenToDepth;
835         int loc_ShadowMap_Parameters;
836         int loc_ShadowMap_TextureScale;
837         int loc_SpecularPower;
838         int loc_Skeletal_Transform12;
839         int loc_UserVec1;
840         int loc_UserVec2;
841         int loc_UserVec3;
842         int loc_UserVec4;
843         int loc_ViewTintColor;
844         int loc_ViewToLight;
845         int loc_ModelToLight;
846         int loc_TexMatrix;
847         int loc_BackgroundTexMatrix;
848         int loc_ModelViewProjectionMatrix;
849         int loc_ModelViewMatrix;
850         int loc_PixelToScreenTexCoord;
851         int loc_ModelToReflectCube;
852         int loc_ShadowMapMatrix;
853         int loc_BloomColorSubtract;
854         int loc_NormalmapScrollBlend;
855         int loc_BounceGridMatrix;
856         int loc_BounceGridIntensity;
857         /// uniform block bindings
858         int ubibind_Skeletal_Transform12_UniformBlock;
859         /// uniform block indices
860         int ubiloc_Skeletal_Transform12_UniformBlock;
861 }
862 r_glsl_permutation_t;
863
864 #define SHADERPERMUTATION_HASHSIZE 256
865
866
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
869 enum
870 {
871         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
877         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
879         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
880         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
881         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
882         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
883         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
884 };
885 #define SHADERSTATICPARMS_COUNT 13
886
887 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
888 static int shaderstaticparms_count = 0;
889
890 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
891 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
892
893 extern qboolean r_shadow_shadowmapsampler;
894 extern int r_shadow_shadowmappcf;
895 qboolean R_CompileShader_CheckStaticParms(void)
896 {
897         static int r_compileshader_staticparms_save[1];
898         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
899         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
900
901         // detect all
902         if (r_glsl_saturation_redcompensate.integer)
903                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
904         if (r_glsl_vertextextureblend_usebothalphas.integer)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
906         if (r_shadow_glossexact.integer)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
908         if (r_glsl_postprocess.integer)
909         {
910                 if (r_glsl_postprocess_uservec1_enable.integer)
911                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
912                 if (r_glsl_postprocess_uservec2_enable.integer)
913                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
914                 if (r_glsl_postprocess_uservec3_enable.integer)
915                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
916                 if (r_glsl_postprocess_uservec4_enable.integer)
917                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
918         }
919         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
920                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
921
922         if (r_shadow_shadowmapsampler)
923                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
924         if (r_shadow_shadowmappcf > 1)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
926         else if (r_shadow_shadowmappcf)
927                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
928         if (r_celshading.integer)
929                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
930         if (r_celoutlines.integer)
931                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
932
933         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
934 }
935
936 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
937         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
938                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
939         else \
940                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
941 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
942 {
943         shaderstaticparms_count = 0;
944
945         // emit all
946         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
947         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
948         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
949         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
950         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
951         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
952         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
953         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
954         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
955         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
956         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
957         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
958         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
959 }
960
961 /// information about each possible shader permutation
962 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
963 /// currently selected permutation
964 r_glsl_permutation_t *r_glsl_permutation;
965 /// storage for permutations linked in the hash table
966 memexpandablearray_t r_glsl_permutationarray;
967
968 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
969 {
970         //unsigned int hashdepth = 0;
971         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
972         r_glsl_permutation_t *p;
973         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
974         {
975                 if (p->mode == mode && p->permutation == permutation)
976                 {
977                         //if (hashdepth > 10)
978                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
979                         return p;
980                 }
981                 //hashdepth++;
982         }
983         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
984         p->mode = mode;
985         p->permutation = permutation;
986         p->hashnext = r_glsl_permutationhash[mode][hashindex];
987         r_glsl_permutationhash[mode][hashindex] = p;
988         //if (hashdepth > 10)
989         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
990         return p;
991 }
992
993 static char *R_ShaderStrCat(const char **strings)
994 {
995         char *string, *s;
996         const char **p = strings;
997         const char *t;
998         size_t len = 0;
999         for (p = strings;(t = *p);p++)
1000                 len += strlen(t);
1001         len++;
1002         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1003         len = 0;
1004         for (p = strings;(t = *p);p++)
1005         {
1006                 len = strlen(t);
1007                 memcpy(s, t, len);
1008                 s += len;
1009         }
1010         *s = 0;
1011         return string;
1012 }
1013
1014 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1015 {
1016         char *shaderstring;
1017         if (!filename || !filename[0])
1018                 return NULL;
1019         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1020         if (!strcmp(filename, "glsl/default.glsl"))
1021         {
1022                 if (builtinonly)
1023                         return R_ShaderStrCat(builtinshaderstrings);
1024                 if (!glslshaderstring)
1025                 {
1026                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1027                         if (glslshaderstring)
1028                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1029                         else
1030                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1031                 }
1032                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1033                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1034                 return shaderstring;
1035         }
1036         if (!strcmp(filename, "hlsl/default.hlsl"))
1037         {
1038                 if (builtinonly)
1039                         return R_ShaderStrCat(builtinhlslshaderstrings);
1040                 if (!hlslshaderstring)
1041                 {
1042                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1043                         if (hlslshaderstring)
1044                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1045                         else
1046                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1047                 }
1048                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1049                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1050                 return shaderstring;
1051         }
1052         // we don't have builtin strings for any other files
1053         if (builtinonly)
1054                 return NULL;
1055         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1056         if (shaderstring)
1057         {
1058                 if (printfromdisknotice)
1059                         Con_DPrintf("from disk %s... ", filename);
1060                 return shaderstring;
1061         }
1062         return shaderstring;
1063 }
1064
1065 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1066 {
1067         int i;
1068         int ubibind;
1069         int sampler;
1070         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1071         char *sourcestring;
1072         char permutationname[256];
1073         int vertstrings_count = 0;
1074         int geomstrings_count = 0;
1075         int fragstrings_count = 0;
1076         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1077         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1078         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1079
1080         if (p->compiled)
1081                 return;
1082         p->compiled = true;
1083         p->program = 0;
1084
1085         permutationname[0] = 0;
1086         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1087
1088         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1089
1090         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1091         if(vid.support.glshaderversion >= 140)
1092         {
1093                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1094                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1095                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1096                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1097                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1098                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1099         }
1100         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1101         else if(vid.support.glshaderversion >= 130)
1102         {
1103                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1104                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1105                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1106                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1107                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1108                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1109         }
1110
1111         // the first pretext is which type of shader to compile as
1112         // (later these will all be bound together as a program object)
1113         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1114         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1115         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1116
1117         // the second pretext is the mode (for example a light source)
1118         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1119         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1120         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1121         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1122
1123         // now add all the permutation pretexts
1124         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1125         {
1126                 if (permutation & (1<<i))
1127                 {
1128                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1129                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1130                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1131                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1132                 }
1133                 else
1134                 {
1135                         // keep line numbers correct
1136                         vertstrings_list[vertstrings_count++] = "\n";
1137                         geomstrings_list[geomstrings_count++] = "\n";
1138                         fragstrings_list[fragstrings_count++] = "\n";
1139                 }
1140         }
1141
1142         // add static parms
1143         R_CompileShader_AddStaticParms(mode, permutation);
1144         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1145         vertstrings_count += shaderstaticparms_count;
1146         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1147         geomstrings_count += shaderstaticparms_count;
1148         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1149         fragstrings_count += shaderstaticparms_count;
1150
1151         // now append the shader text itself
1152         vertstrings_list[vertstrings_count++] = sourcestring;
1153         geomstrings_list[geomstrings_count++] = sourcestring;
1154         fragstrings_list[fragstrings_count++] = sourcestring;
1155
1156         // compile the shader program
1157         if (vertstrings_count + geomstrings_count + fragstrings_count)
1158                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1159         if (p->program)
1160         {
1161                 CHECKGLERROR
1162                 qglUseProgram(p->program);CHECKGLERROR
1163                 // look up all the uniform variable names we care about, so we don't
1164                 // have to look them up every time we set them
1165
1166 #if 0
1167                 // debugging aid
1168                 {
1169                         GLint activeuniformindex = 0;
1170                         GLint numactiveuniforms = 0;
1171                         char uniformname[128];
1172                         GLsizei uniformnamelength = 0;
1173                         GLint uniformsize = 0;
1174                         GLenum uniformtype = 0;
1175                         memset(uniformname, 0, sizeof(uniformname));
1176                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1177                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1178                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1179                         {
1180                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1181                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1182                         }
1183                 }
1184 #endif
1185
1186                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1187                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1188                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1189                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1190                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1191                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1192                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1193                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1194                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1195                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1196                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1197                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1198                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1199                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1200                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1201                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1202                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1203                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1204                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1205                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1206                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1207                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1208                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1209                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1210                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1211                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1212                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1213                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1214                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1215                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1216                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1217                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1218                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1219                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1220                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1221                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1222                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1223                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1224                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1225                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1226                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1227                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1228                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1229                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1230                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1231                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1232                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1233                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1234                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1235                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1236                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1237                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1238                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1239                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1240                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1241                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1242                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1243                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1244                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1245                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1246                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1247                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1248                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1249                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1250                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1251                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1252                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1253                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1254                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1255                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1256                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1257                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1258                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1259                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1260                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1261                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1262                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1263                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1264                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1265                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1266                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1267                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1268                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1269                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1270                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1271                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1272                 // initialize the samplers to refer to the texture units we use
1273                 p->tex_Texture_First = -1;
1274                 p->tex_Texture_Second = -1;
1275                 p->tex_Texture_GammaRamps = -1;
1276                 p->tex_Texture_Normal = -1;
1277                 p->tex_Texture_Color = -1;
1278                 p->tex_Texture_Gloss = -1;
1279                 p->tex_Texture_Glow = -1;
1280                 p->tex_Texture_SecondaryNormal = -1;
1281                 p->tex_Texture_SecondaryColor = -1;
1282                 p->tex_Texture_SecondaryGloss = -1;
1283                 p->tex_Texture_SecondaryGlow = -1;
1284                 p->tex_Texture_Pants = -1;
1285                 p->tex_Texture_Shirt = -1;
1286                 p->tex_Texture_FogHeightTexture = -1;
1287                 p->tex_Texture_FogMask = -1;
1288                 p->tex_Texture_Lightmap = -1;
1289                 p->tex_Texture_Deluxemap = -1;
1290                 p->tex_Texture_Attenuation = -1;
1291                 p->tex_Texture_Cube = -1;
1292                 p->tex_Texture_Refraction = -1;
1293                 p->tex_Texture_Reflection = -1;
1294                 p->tex_Texture_ShadowMap2D = -1;
1295                 p->tex_Texture_CubeProjection = -1;
1296                 p->tex_Texture_ScreenNormalMap = -1;
1297                 p->tex_Texture_ScreenDiffuse = -1;
1298                 p->tex_Texture_ScreenSpecular = -1;
1299                 p->tex_Texture_ReflectMask = -1;
1300                 p->tex_Texture_ReflectCube = -1;
1301                 p->tex_Texture_BounceGrid = -1;
1302                 // bind the texture samplers in use
1303                 sampler = 0;
1304                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1305                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1306                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1307                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1308                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1309                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1310                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1311                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1312                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1313                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1314                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1315                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1316                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1317                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1318                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1319                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1320                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1321                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1322                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1323                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1324                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1325                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1326                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1327                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1328                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1329                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1330                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1331                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1332                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1333                 // get the uniform block indices so we can bind them
1334 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1335                 if (vid.support.arb_uniform_buffer_object)
1336                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1337                 else
1338 #endif
1339                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1340                 // clear the uniform block bindings
1341                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1342                 // bind the uniform blocks in use
1343                 ubibind = 0;
1344 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1345                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1346 #endif
1347                 // we're done compiling and setting up the shader, at least until it is used
1348                 CHECKGLERROR
1349                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1350         }
1351         else
1352                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1353
1354         // free the strings
1355         if (sourcestring)
1356                 Mem_Free(sourcestring);
1357 }
1358
1359 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1360 {
1361         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1362         if (r_glsl_permutation != perm)
1363         {
1364                 r_glsl_permutation = perm;
1365                 if (!r_glsl_permutation->program)
1366                 {
1367                         if (!r_glsl_permutation->compiled)
1368                         {
1369                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1370                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1371                         }
1372                         if (!r_glsl_permutation->program)
1373                         {
1374                                 // remove features until we find a valid permutation
1375                                 int i;
1376                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1377                                 {
1378                                         // reduce i more quickly whenever it would not remove any bits
1379                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1380                                         if (!(permutation & j))
1381                                                 continue;
1382                                         permutation -= j;
1383                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1384                                         if (!r_glsl_permutation->compiled)
1385                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1386                                         if (r_glsl_permutation->program)
1387                                                 break;
1388                                 }
1389                                 if (i >= SHADERPERMUTATION_COUNT)
1390                                 {
1391                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1392                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1393                                         qglUseProgram(0);CHECKGLERROR
1394                                         return; // no bit left to clear, entire mode is broken
1395                                 }
1396                         }
1397                 }
1398                 CHECKGLERROR
1399                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1400         }
1401         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1402         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1403         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1404         CHECKGLERROR
1405 }
1406
1407 #ifdef SUPPORTD3D
1408
1409 #ifdef SUPPORTD3D
1410 #include <d3d9.h>
1411 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1412 extern D3DCAPS9 vid_d3d9caps;
1413 #endif
1414
1415 struct r_hlsl_permutation_s;
1416 typedef struct r_hlsl_permutation_s
1417 {
1418         /// hash lookup data
1419         struct r_hlsl_permutation_s *hashnext;
1420         unsigned int mode;
1421         unsigned int permutation;
1422
1423         /// indicates if we have tried compiling this permutation already
1424         qboolean compiled;
1425         /// NULL if compilation failed
1426         IDirect3DVertexShader9 *vertexshader;
1427         IDirect3DPixelShader9 *pixelshader;
1428 }
1429 r_hlsl_permutation_t;
1430
1431 typedef enum D3DVSREGISTER_e
1432 {
1433         D3DVSREGISTER_TexMatrix = 0, // float4x4
1434         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1435         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1436         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1437         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1438         D3DVSREGISTER_ModelToLight = 20, // float4x4
1439         D3DVSREGISTER_EyePosition = 24,
1440         D3DVSREGISTER_FogPlane = 25,
1441         D3DVSREGISTER_LightDir = 26,
1442         D3DVSREGISTER_LightPosition = 27,
1443 }
1444 D3DVSREGISTER_t;
1445
1446 typedef enum D3DPSREGISTER_e
1447 {
1448         D3DPSREGISTER_Alpha = 0,
1449         D3DPSREGISTER_BloomBlur_Parameters = 1,
1450         D3DPSREGISTER_ClientTime = 2,
1451         D3DPSREGISTER_Color_Ambient = 3,
1452         D3DPSREGISTER_Color_Diffuse = 4,
1453         D3DPSREGISTER_Color_Specular = 5,
1454         D3DPSREGISTER_Color_Glow = 6,
1455         D3DPSREGISTER_Color_Pants = 7,
1456         D3DPSREGISTER_Color_Shirt = 8,
1457         D3DPSREGISTER_DeferredColor_Ambient = 9,
1458         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1459         D3DPSREGISTER_DeferredColor_Specular = 11,
1460         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1461         D3DPSREGISTER_DeferredMod_Specular = 13,
1462         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1463         D3DPSREGISTER_EyePosition = 15, // unused
1464         D3DPSREGISTER_FogColor = 16,
1465         D3DPSREGISTER_FogHeightFade = 17,
1466         D3DPSREGISTER_FogPlane = 18,
1467         D3DPSREGISTER_FogPlaneViewDist = 19,
1468         D3DPSREGISTER_FogRangeRecip = 20,
1469         D3DPSREGISTER_LightColor = 21,
1470         D3DPSREGISTER_LightDir = 22, // unused
1471         D3DPSREGISTER_LightPosition = 23,
1472         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1473         D3DPSREGISTER_PixelSize = 25,
1474         D3DPSREGISTER_ReflectColor = 26,
1475         D3DPSREGISTER_ReflectFactor = 27,
1476         D3DPSREGISTER_ReflectOffset = 28,
1477         D3DPSREGISTER_RefractColor = 29,
1478         D3DPSREGISTER_Saturation = 30,
1479         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1480         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1481         D3DPSREGISTER_ScreenToDepth = 33,
1482         D3DPSREGISTER_ShadowMap_Parameters = 34,
1483         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1484         D3DPSREGISTER_SpecularPower = 36,
1485         D3DPSREGISTER_UserVec1 = 37,
1486         D3DPSREGISTER_UserVec2 = 38,
1487         D3DPSREGISTER_UserVec3 = 39,
1488         D3DPSREGISTER_UserVec4 = 40,
1489         D3DPSREGISTER_ViewTintColor = 41,
1490         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1491         D3DPSREGISTER_BloomColorSubtract = 43,
1492         D3DPSREGISTER_ViewToLight = 44, // float4x4
1493         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1494         D3DPSREGISTER_NormalmapScrollBlend = 52,
1495         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1496         D3DPSREGISTER_OffsetMapping_Bias = 54,
1497         // next at 54
1498 }
1499 D3DPSREGISTER_t;
1500
1501 /// information about each possible shader permutation
1502 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1503 /// currently selected permutation
1504 r_hlsl_permutation_t *r_hlsl_permutation;
1505 /// storage for permutations linked in the hash table
1506 memexpandablearray_t r_hlsl_permutationarray;
1507
1508 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1509 {
1510         //unsigned int hashdepth = 0;
1511         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1512         r_hlsl_permutation_t *p;
1513         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1514         {
1515                 if (p->mode == mode && p->permutation == permutation)
1516                 {
1517                         //if (hashdepth > 10)
1518                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1519                         return p;
1520                 }
1521                 //hashdepth++;
1522         }
1523         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1524         p->mode = mode;
1525         p->permutation = permutation;
1526         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1527         r_hlsl_permutationhash[mode][hashindex] = p;
1528         //if (hashdepth > 10)
1529         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1530         return p;
1531 }
1532
1533 #include <d3dx9.h>
1534 //#include <d3dx9shader.h>
1535 //#include <d3dx9mesh.h>
1536
1537 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1538 {
1539         DWORD *vsbin = NULL;
1540         DWORD *psbin = NULL;
1541         fs_offset_t vsbinsize;
1542         fs_offset_t psbinsize;
1543 //      IDirect3DVertexShader9 *vs = NULL;
1544 //      IDirect3DPixelShader9 *ps = NULL;
1545         ID3DXBuffer *vslog = NULL;
1546         ID3DXBuffer *vsbuffer = NULL;
1547         ID3DXConstantTable *vsconstanttable = NULL;
1548         ID3DXBuffer *pslog = NULL;
1549         ID3DXBuffer *psbuffer = NULL;
1550         ID3DXConstantTable *psconstanttable = NULL;
1551         int vsresult = 0;
1552         int psresult = 0;
1553         char temp[MAX_INPUTLINE];
1554         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1555         char vabuf[1024];
1556         qboolean debugshader = gl_paranoid.integer != 0;
1557         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1558         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1559         if (!debugshader)
1560         {
1561                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1562                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1563         }
1564         if ((!vsbin && vertstring) || (!psbin && fragstring))
1565         {
1566                 const char* dllnames_d3dx9 [] =
1567                 {
1568                         "d3dx9_43.dll",
1569                         "d3dx9_42.dll",
1570                         "d3dx9_41.dll",
1571                         "d3dx9_40.dll",
1572                         "d3dx9_39.dll",
1573                         "d3dx9_38.dll",
1574                         "d3dx9_37.dll",
1575                         "d3dx9_36.dll",
1576                         "d3dx9_35.dll",
1577                         "d3dx9_34.dll",
1578                         "d3dx9_33.dll",
1579                         "d3dx9_32.dll",
1580                         "d3dx9_31.dll",
1581                         "d3dx9_30.dll",
1582                         "d3dx9_29.dll",
1583                         "d3dx9_28.dll",
1584                         "d3dx9_27.dll",
1585                         "d3dx9_26.dll",
1586                         "d3dx9_25.dll",
1587                         "d3dx9_24.dll",
1588                         NULL
1589                 };
1590                 dllhandle_t d3dx9_dll = NULL;
1591                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1592                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1593                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1594                 dllfunction_t d3dx9_dllfuncs[] =
1595                 {
1596                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1597                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1598                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1599                         {NULL, NULL}
1600                 };
1601                 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1602 #ifndef ID3DXBuffer_GetBufferPointer
1603 #if !defined(__cplusplus) || defined(CINTERFACE)
1604 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1605 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1606 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1607 #else
1608 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1609 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1610 #define ID3DXBuffer_Release(p)            (p)->Release()
1611 #endif
1612 #endif
1613                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1614                 {
1615                         DWORD shaderflags = 0;
1616                         if (debugshader)
1617                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1618                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1619                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1620                         if (vertstring && vertstring[0])
1621                         {
1622                                 if (debugshader)
1623                                 {
1624                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1625                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1626                                 }
1627                                 else
1628                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1629                                 if (vsbuffer)
1630                                 {
1631                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1632                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1633                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1634                                         ID3DXBuffer_Release(vsbuffer);
1635                                 }
1636                                 if (vslog)
1637                                 {
1638                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1639                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1640                                         ID3DXBuffer_Release(vslog);
1641                                 }
1642                         }
1643                         if (fragstring && fragstring[0])
1644                         {
1645                                 if (debugshader)
1646                                 {
1647                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1648                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1649                                 }
1650                                 else
1651                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1652                                 if (psbuffer)
1653                                 {
1654                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1655                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1656                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1657                                         ID3DXBuffer_Release(psbuffer);
1658                                 }
1659                                 if (pslog)
1660                                 {
1661                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1662                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1663                                         ID3DXBuffer_Release(pslog);
1664                                 }
1665                         }
1666                         Sys_UnloadLibrary(&d3dx9_dll);
1667                 }
1668                 else
1669                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1670         }
1671         if (vsbin && psbin)
1672         {
1673                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1674                 if (FAILED(vsresult))
1675                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1676                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1677                 if (FAILED(psresult))
1678                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1679         }
1680         // free the shader data
1681         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1682         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1683 }
1684
1685 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1686 {
1687         int i;
1688         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1689         int vertstring_length = 0;
1690         int geomstring_length = 0;
1691         int fragstring_length = 0;
1692         char *t;
1693         char *sourcestring;
1694         char *vertstring, *geomstring, *fragstring;
1695         char permutationname[256];
1696         char cachename[256];
1697         int vertstrings_count = 0;
1698         int geomstrings_count = 0;
1699         int fragstrings_count = 0;
1700         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1701         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1702         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1703
1704         if (p->compiled)
1705                 return;
1706         p->compiled = true;
1707         p->vertexshader = NULL;
1708         p->pixelshader = NULL;
1709
1710         permutationname[0] = 0;
1711         cachename[0] = 0;
1712         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1713
1714         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1715         strlcat(cachename, "hlsl/", sizeof(cachename));
1716
1717         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1718         vertstrings_count = 0;
1719         geomstrings_count = 0;
1720         fragstrings_count = 0;
1721         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1722         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1723         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1724
1725         // the first pretext is which type of shader to compile as
1726         // (later these will all be bound together as a program object)
1727         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1728         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1729         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1730
1731         // the second pretext is the mode (for example a light source)
1732         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1733         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1734         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1735         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1736         strlcat(cachename, modeinfo->name, sizeof(cachename));
1737
1738         // now add all the permutation pretexts
1739         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1740         {
1741                 if (permutation & (1<<i))
1742                 {
1743                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1744                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1745                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1746                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1747                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1748                 }
1749                 else
1750                 {
1751                         // keep line numbers correct
1752                         vertstrings_list[vertstrings_count++] = "\n";
1753                         geomstrings_list[geomstrings_count++] = "\n";
1754                         fragstrings_list[fragstrings_count++] = "\n";
1755                 }
1756         }
1757
1758         // add static parms
1759         R_CompileShader_AddStaticParms(mode, permutation);
1760         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1761         vertstrings_count += shaderstaticparms_count;
1762         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1763         geomstrings_count += shaderstaticparms_count;
1764         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1765         fragstrings_count += shaderstaticparms_count;
1766
1767         // replace spaces in the cachename with _ characters
1768         for (i = 0;cachename[i];i++)
1769                 if (cachename[i] == ' ')
1770                         cachename[i] = '_';
1771
1772         // now append the shader text itself
1773         vertstrings_list[vertstrings_count++] = sourcestring;
1774         geomstrings_list[geomstrings_count++] = sourcestring;
1775         fragstrings_list[fragstrings_count++] = sourcestring;
1776
1777         vertstring_length = 0;
1778         for (i = 0;i < vertstrings_count;i++)
1779                 vertstring_length += strlen(vertstrings_list[i]);
1780         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1781         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1782                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1783
1784         geomstring_length = 0;
1785         for (i = 0;i < geomstrings_count;i++)
1786                 geomstring_length += strlen(geomstrings_list[i]);
1787         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1788         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1789                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1790
1791         fragstring_length = 0;
1792         for (i = 0;i < fragstrings_count;i++)
1793                 fragstring_length += strlen(fragstrings_list[i]);
1794         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1795         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1796                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1797
1798         // try to load the cached shader, or generate one
1799         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1800
1801         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1802                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1803         else
1804                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1805
1806         // free the strings
1807         if (vertstring)
1808                 Mem_Free(vertstring);
1809         if (geomstring)
1810                 Mem_Free(geomstring);
1811         if (fragstring)
1812                 Mem_Free(fragstring);
1813         if (sourcestring)
1814                 Mem_Free(sourcestring);
1815 }
1816
1817 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1818 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1819 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1820 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1821 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1822 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1823
1824 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1825 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1826 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1827 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1828 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1829 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1830
1831 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1832 {
1833         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1834         if (r_hlsl_permutation != perm)
1835         {
1836                 r_hlsl_permutation = perm;
1837                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1838                 {
1839                         if (!r_hlsl_permutation->compiled)
1840                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1841                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1842                         {
1843                                 // remove features until we find a valid permutation
1844                                 int i;
1845                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1846                                 {
1847                                         // reduce i more quickly whenever it would not remove any bits
1848                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1849                                         if (!(permutation & j))
1850                                                 continue;
1851                                         permutation -= j;
1852                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1853                                         if (!r_hlsl_permutation->compiled)
1854                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1855                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1856                                                 break;
1857                                 }
1858                                 if (i >= SHADERPERMUTATION_COUNT)
1859                                 {
1860                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1861                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1862                                         return; // no bit left to clear, entire mode is broken
1863                                 }
1864                         }
1865                 }
1866                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1867                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1868         }
1869         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1870         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1871         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1872 }
1873 #endif
1874
1875 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1876 {
1877         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1878         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1879         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1880         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1881 }
1882
1883 void R_GLSL_Restart_f(void)
1884 {
1885         unsigned int i, limit;
1886         if (glslshaderstring)
1887                 Mem_Free(glslshaderstring);
1888         glslshaderstring = NULL;
1889         if (hlslshaderstring)
1890                 Mem_Free(hlslshaderstring);
1891         hlslshaderstring = NULL;
1892         switch(vid.renderpath)
1893         {
1894         case RENDERPATH_D3D9:
1895 #ifdef SUPPORTD3D
1896                 {
1897                         r_hlsl_permutation_t *p;
1898                         r_hlsl_permutation = NULL;
1899                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1900                         for (i = 0;i < limit;i++)
1901                         {
1902                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1903                                 {
1904                                         if (p->vertexshader)
1905                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1906                                         if (p->pixelshader)
1907                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1908                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1909                                 }
1910                         }
1911                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1912                 }
1913 #endif
1914                 break;
1915         case RENDERPATH_D3D10:
1916                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1917                 break;
1918         case RENDERPATH_D3D11:
1919                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920                 break;
1921         case RENDERPATH_GL20:
1922         case RENDERPATH_GLES2:
1923                 {
1924                         r_glsl_permutation_t *p;
1925                         r_glsl_permutation = NULL;
1926                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1927                         for (i = 0;i < limit;i++)
1928                         {
1929                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1930                                 {
1931                                         GL_Backend_FreeProgram(p->program);
1932                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1933                                 }
1934                         }
1935                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1936                 }
1937                 break;
1938         case RENDERPATH_GL11:
1939         case RENDERPATH_GL13:
1940         case RENDERPATH_GLES1:
1941                 break;
1942         case RENDERPATH_SOFT:
1943                 break;
1944         }
1945 }
1946
1947 static void R_GLSL_DumpShader_f(void)
1948 {
1949         int i, language, mode, dupe;
1950         char *text;
1951         shadermodeinfo_t *modeinfo;
1952         qfile_t *file;
1953
1954         for (language = 0;language < 2;language++)
1955         {
1956                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1957                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1958                 {
1959                         // don't dump the same file multiple times (most or all shaders come from the same file)
1960                         for (dupe = mode - 1;dupe >= 0;dupe--)
1961                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1962                                         break;
1963                         if (dupe >= 0)
1964                                 continue;
1965                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1966                         if (!text)
1967                                 continue;
1968                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1969                         if (file)
1970                         {
1971                                 FS_Print(file, "/* The engine may define the following macros:\n");
1972                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1973                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1974                                         FS_Print(file, modeinfo[i].pretext);
1975                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1976                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1977                                 FS_Print(file, "*/\n");
1978                                 FS_Print(file, text);
1979                                 FS_Close(file);
1980                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1981                         }
1982                         else
1983                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1984                         Mem_Free(text);
1985                 }
1986         }
1987 }
1988
1989 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1990 {
1991         unsigned int permutation = 0;
1992         if (r_trippy.integer && !notrippy)
1993                 permutation |= SHADERPERMUTATION_TRIPPY;
1994         permutation |= SHADERPERMUTATION_VIEWTINT;
1995         if (first)
1996                 permutation |= SHADERPERMUTATION_DIFFUSE;
1997         if (second)
1998                 permutation |= SHADERPERMUTATION_SPECULAR;
1999         if (texturemode == GL_MODULATE)
2000                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2001         else if (texturemode == GL_ADD)
2002                 permutation |= SHADERPERMUTATION_GLOW;
2003         else if (texturemode == GL_DECAL)
2004                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2005         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2006                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2007         if (suppresstexalpha)
2008                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2009         if (!second)
2010                 texturemode = GL_MODULATE;
2011         if (vid.allowalphatocoverage)
2012                 GL_AlphaToCoverage(false);
2013         switch (vid.renderpath)
2014         {
2015         case RENDERPATH_D3D9:
2016 #ifdef SUPPORTD3D
2017                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2018                 R_Mesh_TexBind(GL20TU_FIRST , first );
2019                 R_Mesh_TexBind(GL20TU_SECOND, second);
2020                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2021                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2022 #endif
2023                 break;
2024         case RENDERPATH_D3D10:
2025                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2026                 break;
2027         case RENDERPATH_D3D11:
2028                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2029                 break;
2030         case RENDERPATH_GL20:
2031         case RENDERPATH_GLES2:
2032                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2033                 if (r_glsl_permutation->tex_Texture_First >= 0)
2034                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2035                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2036                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2037                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2038                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2039                 break;
2040         case RENDERPATH_GL13:
2041         case RENDERPATH_GLES1:
2042                 R_Mesh_TexBind(0, first );
2043                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2044                 R_Mesh_TexMatrix(0, NULL);
2045                 R_Mesh_TexBind(1, second);
2046                 if (second)
2047                 {
2048                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2049                         R_Mesh_TexMatrix(1, NULL);
2050                 }
2051                 break;
2052         case RENDERPATH_GL11:
2053                 R_Mesh_TexBind(0, first );
2054                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2055                 R_Mesh_TexMatrix(0, NULL);
2056                 break;
2057         case RENDERPATH_SOFT:
2058                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2059                 R_Mesh_TexBind(GL20TU_FIRST , first );
2060                 R_Mesh_TexBind(GL20TU_SECOND, second);
2061                 break;
2062         }
2063 }
2064
2065 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2066 {
2067         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2068 }
2069
2070 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2071 {
2072         unsigned int permutation = 0;
2073         if (r_trippy.integer && !notrippy)
2074                 permutation |= SHADERPERMUTATION_TRIPPY;
2075         if (depthrgb)
2076                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2077         if (skeletal)
2078                 permutation |= SHADERPERMUTATION_SKELETAL;
2079
2080         if (vid.allowalphatocoverage)
2081                 GL_AlphaToCoverage(false);
2082         switch (vid.renderpath)
2083         {
2084         case RENDERPATH_D3D9:
2085 #ifdef SUPPORTD3D
2086                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2087 #endif
2088                 break;
2089         case RENDERPATH_D3D10:
2090                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2091                 break;
2092         case RENDERPATH_D3D11:
2093                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2094                 break;
2095         case RENDERPATH_GL20:
2096         case RENDERPATH_GLES2:
2097                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2098 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2099                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2100 #endif
2101                 break;
2102         case RENDERPATH_GL13:
2103         case RENDERPATH_GLES1:
2104                 R_Mesh_TexBind(0, 0);
2105                 R_Mesh_TexBind(1, 0);
2106                 break;
2107         case RENDERPATH_GL11:
2108                 R_Mesh_TexBind(0, 0);
2109                 break;
2110         case RENDERPATH_SOFT:
2111                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2112                 break;
2113         }
2114 }
2115
2116 extern qboolean r_shadow_usingdeferredprepass;
2117 extern rtexture_t *r_shadow_attenuationgradienttexture;
2118 extern rtexture_t *r_shadow_attenuation2dtexture;
2119 extern rtexture_t *r_shadow_attenuation3dtexture;
2120 extern qboolean r_shadow_usingshadowmap2d;
2121 extern qboolean r_shadow_usingshadowmaportho;
2122 extern float r_shadow_shadowmap_texturescale[2];
2123 extern float r_shadow_shadowmap_parameters[4];
2124 extern qboolean r_shadow_shadowmapvsdct;
2125 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2126 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2127 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2128 extern matrix4x4_t r_shadow_shadowmapmatrix;
2129 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2130 extern int r_shadow_prepass_width;
2131 extern int r_shadow_prepass_height;
2132 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2133 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2134 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2135 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2136
2137 #define BLENDFUNC_ALLOWS_COLORMOD      1
2138 #define BLENDFUNC_ALLOWS_FOG           2
2139 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2140 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2141 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2142 static int R_BlendFuncFlags(int src, int dst)
2143 {
2144         int r = 0;
2145
2146         // a blendfunc allows colormod if:
2147         // a) it can never keep the destination pixel invariant, or
2148         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2149         // this is to prevent unintended side effects from colormod
2150
2151         // a blendfunc allows fog if:
2152         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2153         // this is to prevent unintended side effects from fog
2154
2155         // these checks are the output of fogeval.pl
2156
2157         r |= BLENDFUNC_ALLOWS_COLORMOD;
2158         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2159         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2160         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2161         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2162         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2163         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2164         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2165         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2166         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2167         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2168         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2169         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2170         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2171         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2172         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2173         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2174         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2175         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2176         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2177         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2178         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179
2180         return r;
2181 }
2182
2183 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2184 {
2185         // select a permutation of the lighting shader appropriate to this
2186         // combination of texture, entity, light source, and fogging, only use the
2187         // minimum features necessary to avoid wasting rendering time in the
2188         // fragment shader on features that are not being used
2189         unsigned int permutation = 0;
2190         unsigned int mode = 0;
2191         int blendfuncflags;
2192         static float dummy_colormod[3] = {1, 1, 1};
2193         float *colormod = rsurface.colormod;
2194         float m16f[16];
2195         matrix4x4_t tempmatrix;
2196         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2197         if (r_trippy.integer && !notrippy)
2198                 permutation |= SHADERPERMUTATION_TRIPPY;
2199         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2200                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2201         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2202                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2203         if (rsurfacepass == RSURFPASS_BACKGROUND)
2204         {
2205                 // distorted background
2206                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2207                 {
2208                         mode = SHADERMODE_WATER;
2209                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2210                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2211                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2212                         {
2213                                 // this is the right thing to do for wateralpha
2214                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2215                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2216                         }
2217                         else
2218                         {
2219                                 // this is the right thing to do for entity alpha
2220                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2221                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2222                         }
2223                 }
2224                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2225                 {
2226                         mode = SHADERMODE_REFRACTION;
2227                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2228                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2229                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2230                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2231                 }
2232                 else
2233                 {
2234                         mode = SHADERMODE_GENERIC;
2235                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2236                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2237                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2238                 }
2239                 if (vid.allowalphatocoverage)
2240                         GL_AlphaToCoverage(false);
2241         }
2242         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2243         {
2244                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2245                 {
2246                         switch(rsurface.texture->offsetmapping)
2247                         {
2248                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2249                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2250                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2251                         case OFFSETMAPPING_OFF: break;
2252                         }
2253                 }
2254                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2255                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2256                 // normalmap (deferred prepass), may use alpha test on diffuse
2257                 mode = SHADERMODE_DEFERREDGEOMETRY;
2258                 GL_BlendFunc(GL_ONE, GL_ZERO);
2259                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2260                 if (vid.allowalphatocoverage)
2261                         GL_AlphaToCoverage(false);
2262         }
2263         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2264         {
2265                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2266                 {
2267                         switch(rsurface.texture->offsetmapping)
2268                         {
2269                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2270                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2271                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2272                         case OFFSETMAPPING_OFF: break;
2273                         }
2274                 }
2275                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2276                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2277                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2278                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2279                 // light source
2280                 mode = SHADERMODE_LIGHTSOURCE;
2281                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2282                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2283                 if (diffusescale > 0)
2284                         permutation |= SHADERPERMUTATION_DIFFUSE;
2285                 if (specularscale > 0)
2286                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2287                 if (r_refdef.fogenabled)
2288                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2289                 if (rsurface.texture->colormapping)
2290                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2291                 if (r_shadow_usingshadowmap2d)
2292                 {
2293                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2294                         if(r_shadow_shadowmapvsdct)
2295                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2296
2297                         if (r_shadow_shadowmap2ddepthbuffer)
2298                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2299                 }
2300                 if (rsurface.texture->reflectmasktexture)
2301                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2302                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2303                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2304                 if (vid.allowalphatocoverage)
2305                         GL_AlphaToCoverage(false);
2306         }
2307         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2308         {
2309                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2310                 {
2311                         switch(rsurface.texture->offsetmapping)
2312                         {
2313                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2314                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2315                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2316                         case OFFSETMAPPING_OFF: break;
2317                         }
2318                 }
2319                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2320                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2321                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2322                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2323                 // unshaded geometry (fullbright or ambient model lighting)
2324                 mode = SHADERMODE_FLATCOLOR;
2325                 ambientscale = diffusescale = specularscale = 0;
2326                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2327                         permutation |= SHADERPERMUTATION_GLOW;
2328                 if (r_refdef.fogenabled)
2329                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2330                 if (rsurface.texture->colormapping)
2331                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2332                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2333                 {
2334                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2335                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2336
2337                         if (r_shadow_shadowmap2ddepthbuffer)
2338                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2339                 }
2340                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2341                         permutation |= SHADERPERMUTATION_REFLECTION;
2342                 if (rsurface.texture->reflectmasktexture)
2343                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2344                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2345                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2346                 // when using alphatocoverage, we don't need alphakill
2347                 if (vid.allowalphatocoverage)
2348                 {
2349                         if (r_transparent_alphatocoverage.integer)
2350                         {
2351                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2352                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2353                         }
2354                         else
2355                                 GL_AlphaToCoverage(false);
2356                 }
2357         }
2358         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2359         {
2360                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2361                 {
2362                         switch(rsurface.texture->offsetmapping)
2363                         {
2364                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2365                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2366                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2367                         case OFFSETMAPPING_OFF: break;
2368                         }
2369                 }
2370                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2371                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2372                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2373                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2374                 // directional model lighting
2375                 mode = SHADERMODE_LIGHTDIRECTION;
2376                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2377                         permutation |= SHADERPERMUTATION_GLOW;
2378                 permutation |= SHADERPERMUTATION_DIFFUSE;
2379                 if (specularscale > 0)
2380                         permutation |= SHADERPERMUTATION_SPECULAR;
2381                 if (r_refdef.fogenabled)
2382                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2383                 if (rsurface.texture->colormapping)
2384                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2385                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2386                 {
2387                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2388                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2389
2390                         if (r_shadow_shadowmap2ddepthbuffer)
2391                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2392                 }
2393                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2394                         permutation |= SHADERPERMUTATION_REFLECTION;
2395                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2396                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2397                 if (rsurface.texture->reflectmasktexture)
2398                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2399                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2400                 {
2401                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2402                         if (r_shadow_bouncegriddirectional)
2403                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2404                 }
2405                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2406                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2407                 // when using alphatocoverage, we don't need alphakill
2408                 if (vid.allowalphatocoverage)
2409                 {
2410                         if (r_transparent_alphatocoverage.integer)
2411                         {
2412                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2413                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2414                         }
2415                         else
2416                                 GL_AlphaToCoverage(false);
2417                 }
2418         }
2419         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2420         {
2421                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2422                 {
2423                         switch(rsurface.texture->offsetmapping)
2424                         {
2425                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2426                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2427                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2428                         case OFFSETMAPPING_OFF: break;
2429                         }
2430                 }
2431                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2432                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2434                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2435                 // ambient model lighting
2436                 mode = SHADERMODE_LIGHTDIRECTION;
2437                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2438                         permutation |= SHADERPERMUTATION_GLOW;
2439                 if (r_refdef.fogenabled)
2440                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2441                 if (rsurface.texture->colormapping)
2442                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2443                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2444                 {
2445                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2446                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2447
2448                         if (r_shadow_shadowmap2ddepthbuffer)
2449                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2450                 }
2451                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2452                         permutation |= SHADERPERMUTATION_REFLECTION;
2453                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2454                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2455                 if (rsurface.texture->reflectmasktexture)
2456                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2457                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2458                 {
2459                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2460                         if (r_shadow_bouncegriddirectional)
2461                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2462                 }
2463                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2464                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2465                 // when using alphatocoverage, we don't need alphakill
2466                 if (vid.allowalphatocoverage)
2467                 {
2468                         if (r_transparent_alphatocoverage.integer)
2469                         {
2470                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2471                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2472                         }
2473                         else
2474                                 GL_AlphaToCoverage(false);
2475                 }
2476         }
2477         else
2478         {
2479                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2480                 {
2481                         switch(rsurface.texture->offsetmapping)
2482                         {
2483                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2484                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2485                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2486                         case OFFSETMAPPING_OFF: break;
2487                         }
2488                 }
2489                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2490                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2491                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2492                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2493                 // lightmapped wall
2494                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2495                         permutation |= SHADERPERMUTATION_GLOW;
2496                 if (r_refdef.fogenabled)
2497                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2498                 if (rsurface.texture->colormapping)
2499                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2500                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2501                 {
2502                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2503                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2504
2505                         if (r_shadow_shadowmap2ddepthbuffer)
2506                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2507                 }
2508                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2509                         permutation |= SHADERPERMUTATION_REFLECTION;
2510                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2511                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2512                 if (rsurface.texture->reflectmasktexture)
2513                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2514                 if (FAKELIGHT_ENABLED)
2515                 {
2516                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2517                         mode = SHADERMODE_FAKELIGHT;
2518                         permutation |= SHADERPERMUTATION_DIFFUSE;
2519                         if (specularscale > 0)
2520                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2521                 }
2522                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2523                 {
2524                         // deluxemapping (light direction texture)
2525                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2526                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2527                         else
2528                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2529                         permutation |= SHADERPERMUTATION_DIFFUSE;
2530                         if (specularscale > 0)
2531                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2532                 }
2533                 else if (r_glsl_deluxemapping.integer >= 2)
2534                 {
2535                         // fake deluxemapping (uniform light direction in tangentspace)
2536                         if (rsurface.uselightmaptexture)
2537                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2538                         else
2539                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2540                         permutation |= SHADERPERMUTATION_DIFFUSE;
2541                         if (specularscale > 0)
2542                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2543                 }
2544                 else if (rsurface.uselightmaptexture)
2545                 {
2546                         // ordinary lightmapping (q1bsp, q3bsp)
2547                         mode = SHADERMODE_LIGHTMAP;
2548                 }
2549                 else
2550                 {
2551                         // ordinary vertex coloring (q3bsp)
2552                         mode = SHADERMODE_VERTEXCOLOR;
2553                 }
2554                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2555                 {
2556                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2557                         if (r_shadow_bouncegriddirectional)
2558                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2559                 }
2560                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2561                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2562                 // when using alphatocoverage, we don't need alphakill
2563                 if (vid.allowalphatocoverage)
2564                 {
2565                         if (r_transparent_alphatocoverage.integer)
2566                         {
2567                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2568                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2569                         }
2570                         else
2571                                 GL_AlphaToCoverage(false);
2572                 }
2573         }
2574         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2575                 colormod = dummy_colormod;
2576         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2577                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2578         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2579                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2580         switch(vid.renderpath)
2581         {
2582         case RENDERPATH_D3D9:
2583 #ifdef SUPPORTD3D
2584                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2585                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2586                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2587                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2588                 if (mode == SHADERMODE_LIGHTSOURCE)
2589                 {
2590                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2591                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2592                 }
2593                 else
2594                 {
2595                         if (mode == SHADERMODE_LIGHTDIRECTION)
2596                         {
2597                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2598                         }
2599                 }
2600                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2601                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2602                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2603                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2604                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2605
2606                 if (mode == SHADERMODE_LIGHTSOURCE)
2607                 {
2608                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2609                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2610                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2611                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2612                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2613
2614                         // additive passes are only darkened by fog, not tinted
2615                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2616                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2617                 }
2618                 else
2619                 {
2620                         if (mode == SHADERMODE_FLATCOLOR)
2621                         {
2622                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2623                         }
2624                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2625                         {
2626                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2627                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2628                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2629                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2630                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2631                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2632                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2633                         }
2634                         else
2635                         {
2636                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2637                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2638                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2639                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2640                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2641                         }
2642                         // additive passes are only darkened by fog, not tinted
2643                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2644                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2645                         else
2646                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2647                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2648                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2649                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2650                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2651                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2652                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2653                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2654                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2655                         if (mode == SHADERMODE_WATER)
2656                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2657                 }
2658                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2659                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2660                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2661                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2662                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2663                 if (rsurface.texture->pantstexture)
2664                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2665                 else
2666                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2667                 if (rsurface.texture->shirttexture)
2668                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2669                 else
2670                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2671                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2672                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2673                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2674                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2675                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2676                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2677                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2678                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2679                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2680                         );
2681                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2682                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2683                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2684                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2685
2686                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2687                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2688                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2689                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2690                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2691                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2692                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2693                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2694                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2695                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2696                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2697                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2698                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2699                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2700                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2701                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2702                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2703                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2704                 {
2705                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2706                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2707                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2708                 }
2709                 else
2710                 {
2711                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2712                 }
2713 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2714                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2715                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2716                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2717                 {
2718                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2719                         if (rsurface.rtlight)
2720                         {
2721                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2722                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2723                         }
2724                 }
2725 #endif
2726                 break;
2727         case RENDERPATH_D3D10:
2728                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2729                 break;
2730         case RENDERPATH_D3D11:
2731                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2732                 break;
2733         case RENDERPATH_GL20:
2734         case RENDERPATH_GLES2:
2735                 if (!vid.useinterleavedarrays)
2736                 {
2737                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2738                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2739                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2740                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2741                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2742                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2743                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2744                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2745                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2746                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2747                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2748                 }
2749                 else
2750                 {
2751                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2752                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2753                 }
2754                 // this has to be after RSurf_PrepareVerticesForBatch
2755                 if (rsurface.batchskeletaltransform3x4buffer)
2756                         permutation |= SHADERPERMUTATION_SKELETAL;
2757                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2758 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2759                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2760 #endif
2761                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2762                 if (mode == SHADERMODE_LIGHTSOURCE)
2763                 {
2764                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2765                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2766                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2767                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2768                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2769                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2770         
2771                         // additive passes are only darkened by fog, not tinted
2772                         if (r_glsl_permutation->loc_FogColor >= 0)
2773                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2774                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2775                 }
2776                 else
2777                 {
2778                         if (mode == SHADERMODE_FLATCOLOR)
2779                         {
2780                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2781                         }
2782                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2783                         {
2784                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2785                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2786                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2787                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2788                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2789                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2790                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2791                         }
2792                         else
2793                         {
2794                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2795                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2796                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2797                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2798                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2799                         }
2800                         // additive passes are only darkened by fog, not tinted
2801                         if (r_glsl_permutation->loc_FogColor >= 0)
2802                         {
2803                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2804                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2805                                 else
2806                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2807                         }
2808                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2809                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2810                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2811                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2812                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2813                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2814                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2815                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2816                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2817                 }
2818                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2819                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2820                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2821                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2822                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2823
2824                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2825                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2826                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2827                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2828                 {
2829                         if (rsurface.texture->pantstexture)
2830                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2831                         else
2832                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2833                 }
2834                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2835                 {
2836                         if (rsurface.texture->shirttexture)
2837                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2838                         else
2839                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2840                 }
2841                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2842                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2843                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2844                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2845                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2846                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2847                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2848                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2849                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2850                         );
2851                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2852                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2853                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2854                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2855                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2856                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2857
2858                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2859                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2860                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2861                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2862                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2863                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2864                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2865                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2866                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2867                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2868                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2869                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2870                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2871                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2872                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2873                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2874                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2875                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2876                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2877                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2878                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2879                 {
2880                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2881                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2882                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2883                 }
2884                 else
2885                 {
2886                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2887                 }
2888                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2889                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2890                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2891                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2892                 {
2893                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2894                         if (rsurface.rtlight)
2895                         {
2896                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2897                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2898                         }
2899                 }
2900                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2901                 CHECKGLERROR
2902                 break;
2903         case RENDERPATH_GL11:
2904         case RENDERPATH_GL13:
2905         case RENDERPATH_GLES1:
2906                 break;
2907         case RENDERPATH_SOFT:
2908                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2909                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2910                 R_SetupShader_SetPermutationSoft(mode, permutation);
2911                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2912                 if (mode == SHADERMODE_LIGHTSOURCE)
2913                 {
2914                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2915                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2916                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2917                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2918                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2919                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2920         
2921                         // additive passes are only darkened by fog, not tinted
2922                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2923                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2924                 }
2925                 else
2926                 {
2927                         if (mode == SHADERMODE_FLATCOLOR)
2928                         {
2929                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2930                         }
2931                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2932                         {
2933                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2934                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2935                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2936                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2937                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2938                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2939                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2940                         }
2941                         else
2942                         {
2943                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2944                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2945                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2946                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2947                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2948                         }
2949                         // additive passes are only darkened by fog, not tinted
2950                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2951                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2952                         else
2953                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2954                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2955                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2956                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2957                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2958                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2959                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2960                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2961                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2962                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2963                 }
2964                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2965                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2966                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2967                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2968                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2969
2970                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2971                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2972                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2973                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2974                 {
2975                         if (rsurface.texture->pantstexture)
2976                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2977                         else
2978                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2979                 }
2980                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2981                 {
2982                         if (rsurface.texture->shirttexture)
2983                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2984                         else
2985                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2986                 }
2987                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2988                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2989                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2990                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2991                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2992                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2993                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2994                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2995                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2996                         );
2997                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2998                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2999                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3000                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3001
3002                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3003                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3004                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3005                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3006                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3007                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3008                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3009                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3010                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3011                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3012                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3013                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3014                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3015                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3016                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3017                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3018                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3019                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3020                 {
3021                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3022                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3023                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3024                 }
3025                 else
3026                 {
3027                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3028                 }
3029 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3030                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3031                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3032                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3033                 {
3034                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3035                         if (rsurface.rtlight)
3036                         {
3037                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3038                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3039                         }
3040                 }
3041                 break;
3042         }
3043 }
3044
3045 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3046 {
3047         // select a permutation of the lighting shader appropriate to this
3048         // combination of texture, entity, light source, and fogging, only use the
3049         // minimum features necessary to avoid wasting rendering time in the
3050         // fragment shader on features that are not being used
3051         unsigned int permutation = 0;
3052         unsigned int mode = 0;
3053         const float *lightcolorbase = rtlight->currentcolor;
3054         float ambientscale = rtlight->ambientscale;
3055         float diffusescale = rtlight->diffusescale;
3056         float specularscale = rtlight->specularscale;
3057         // this is the location of the light in view space
3058         vec3_t viewlightorigin;
3059         // this transforms from view space (camera) to light space (cubemap)
3060         matrix4x4_t viewtolight;
3061         matrix4x4_t lighttoview;
3062         float viewtolight16f[16];
3063         // light source
3064         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3065         if (rtlight->currentcubemap != r_texture_whitecube)
3066                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3067         if (diffusescale > 0)
3068                 permutation |= SHADERPERMUTATION_DIFFUSE;
3069         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3070                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3071         if (r_shadow_usingshadowmap2d)
3072         {
3073                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3074                 if (r_shadow_shadowmapvsdct)
3075                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3076
3077                 if (r_shadow_shadowmap2ddepthbuffer)
3078                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3079         }
3080         if (vid.allowalphatocoverage)
3081                 GL_AlphaToCoverage(false);
3082         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3083         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3084         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3085         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3086         switch(vid.renderpath)
3087         {
3088         case RENDERPATH_D3D9:
3089 #ifdef SUPPORTD3D
3090                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3091                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3092                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3093                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3094                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3095                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3096                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3097                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3098                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3099                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3100                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3101
3102                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3103                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3104                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3105                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3106                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3107 #endif
3108                 break;
3109         case RENDERPATH_D3D10:
3110                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3111                 break;
3112         case RENDERPATH_D3D11:
3113                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3114                 break;
3115         case RENDERPATH_GL20:
3116         case RENDERPATH_GLES2:
3117                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3118                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3119                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3120                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3121                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3122                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3123                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3124                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3125                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3126                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3127                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3128
3129                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3130                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3131                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3132                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3133                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3134                 break;
3135         case RENDERPATH_GL11:
3136         case RENDERPATH_GL13:
3137         case RENDERPATH_GLES1:
3138                 break;
3139         case RENDERPATH_SOFT:
3140                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3141                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3142                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3143                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3144                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3145                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3146                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3147                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3148                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3149                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3150                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3151
3152                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3153                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3154                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3155                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3156                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3157                 break;
3158         }
3159 }
3160
3161 #define SKINFRAME_HASH 1024
3162
3163 typedef struct
3164 {
3165         int loadsequence; // incremented each level change
3166         memexpandablearray_t array;
3167         skinframe_t *hash[SKINFRAME_HASH];
3168 }
3169 r_skinframe_t;
3170 r_skinframe_t r_skinframe;
3171
3172 void R_SkinFrame_PrepareForPurge(void)
3173 {
3174         r_skinframe.loadsequence++;
3175         // wrap it without hitting zero
3176         if (r_skinframe.loadsequence >= 200)
3177                 r_skinframe.loadsequence = 1;
3178 }
3179
3180 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3181 {
3182         if (!skinframe)
3183                 return;
3184         // mark the skinframe as used for the purging code
3185         skinframe->loadsequence = r_skinframe.loadsequence;
3186 }
3187
3188 void R_SkinFrame_Purge(void)
3189 {
3190         int i;
3191         skinframe_t *s;
3192         for (i = 0;i < SKINFRAME_HASH;i++)
3193         {
3194                 for (s = r_skinframe.hash[i];s;s = s->next)
3195                 {
3196                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3197                         {
3198                                 if (s->merged == s->base)
3199                                         s->merged = NULL;
3200                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3201                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3202                                 R_PurgeTexture(s->merged);s->merged = NULL;
3203                                 R_PurgeTexture(s->base  );s->base   = NULL;
3204                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3205                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3206                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3207                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3208                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3209                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3210                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3211                                 s->loadsequence = 0;
3212                         }
3213                 }
3214         }
3215 }
3216
3217 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3218         skinframe_t *item;
3219         char basename[MAX_QPATH];
3220
3221         Image_StripImageExtension(name, basename, sizeof(basename));
3222
3223         if( last == NULL ) {
3224                 int hashindex;
3225                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3226                 item = r_skinframe.hash[hashindex];
3227         } else {
3228                 item = last->next;
3229         }
3230
3231         // linearly search through the hash bucket
3232         for( ; item ; item = item->next ) {
3233                 if( !strcmp( item->basename, basename ) ) {
3234                         return item;
3235                 }
3236         }
3237         return NULL;
3238 }
3239
3240 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3241 {
3242         skinframe_t *item;
3243         int hashindex;
3244         char basename[MAX_QPATH];
3245
3246         Image_StripImageExtension(name, basename, sizeof(basename));
3247
3248         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3249         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3250                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3251                         break;
3252
3253         if (!item) {
3254                 rtexture_t *dyntexture;
3255                 // check whether its a dynamic texture
3256                 dyntexture = CL_GetDynTexture( basename );
3257                 if (!add && !dyntexture)
3258                         return NULL;
3259                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3260                 memset(item, 0, sizeof(*item));
3261                 strlcpy(item->basename, basename, sizeof(item->basename));
3262                 item->base = dyntexture; // either NULL or dyntexture handle
3263                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3264                 item->comparewidth = comparewidth;
3265                 item->compareheight = compareheight;
3266                 item->comparecrc = comparecrc;
3267                 item->next = r_skinframe.hash[hashindex];
3268                 r_skinframe.hash[hashindex] = item;
3269         }
3270         else if (textureflags & TEXF_FORCE_RELOAD)
3271         {
3272                 rtexture_t *dyntexture;
3273                 // check whether its a dynamic texture
3274                 dyntexture = CL_GetDynTexture( basename );
3275                 if (!add && !dyntexture)
3276                         return NULL;
3277                 if (item->merged == item->base)
3278                         item->merged = NULL;
3279                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3280                 R_PurgeTexture(item->stain );item->stain  = NULL;
3281                 R_PurgeTexture(item->merged);item->merged = NULL;
3282                 R_PurgeTexture(item->base  );item->base   = NULL;
3283                 R_PurgeTexture(item->pants );item->pants  = NULL;
3284                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3285                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3286                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3287                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3288                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3289         R_PurgeTexture(item->reflect);item->reflect = NULL;
3290                 item->loadsequence = 0;
3291         }
3292         else if( item->base == NULL )
3293         {
3294                 rtexture_t *dyntexture;
3295                 // check whether its a dynamic texture
3296                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3297                 dyntexture = CL_GetDynTexture( basename );
3298                 item->base = dyntexture; // either NULL or dyntexture handle
3299         }
3300
3301         R_SkinFrame_MarkUsed(item);
3302         return item;
3303 }
3304
3305 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3306         { \
3307                 unsigned long long avgcolor[5], wsum; \
3308                 int pix, comp, w; \
3309                 avgcolor[0] = 0; \
3310                 avgcolor[1] = 0; \
3311                 avgcolor[2] = 0; \
3312                 avgcolor[3] = 0; \
3313                 avgcolor[4] = 0; \
3314                 wsum = 0; \
3315                 for(pix = 0; pix < cnt; ++pix) \
3316                 { \
3317                         w = 0; \
3318                         for(comp = 0; comp < 3; ++comp) \
3319                                 w += getpixel; \
3320                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3321                         { \
3322                                 ++wsum; \
3323                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3324                                 w = getpixel; \
3325                                 for(comp = 0; comp < 3; ++comp) \
3326                                         avgcolor[comp] += getpixel * w; \
3327                                 avgcolor[3] += w; \
3328                         } \
3329                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3330                         avgcolor[4] += getpixel; \
3331                 } \
3332                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3333                         avgcolor[3] = 1; \
3334                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3335                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3336                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3337                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3338         }
3339
3340 extern cvar_t gl_picmip;
3341 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3342 {
3343         int j;
3344         unsigned char *pixels;
3345         unsigned char *bumppixels;
3346         unsigned char *basepixels = NULL;
3347         int basepixels_width = 0;
3348         int basepixels_height = 0;
3349         skinframe_t *skinframe;
3350         rtexture_t *ddsbase = NULL;
3351         qboolean ddshasalpha = false;
3352         float ddsavgcolor[4];
3353         char basename[MAX_QPATH];
3354         int miplevel = R_PicmipForFlags(textureflags);
3355         int savemiplevel = miplevel;
3356         int mymiplevel;
3357         char vabuf[1024];
3358
3359         if (cls.state == ca_dedicated)
3360                 return NULL;
3361
3362         // return an existing skinframe if already loaded
3363         // if loading of the first image fails, don't make a new skinframe as it
3364         // would cause all future lookups of this to be missing
3365         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3366         if (skinframe && skinframe->base)
3367                 return skinframe;
3368
3369         Image_StripImageExtension(name, basename, sizeof(basename));
3370
3371         // check for DDS texture file first
3372         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3373         {
3374                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3375                 if (basepixels == NULL)
3376                         return NULL;
3377         }
3378
3379         // FIXME handle miplevel
3380
3381         if (developer_loading.integer)
3382                 Con_Printf("loading skin \"%s\"\n", name);
3383
3384         // we've got some pixels to store, so really allocate this new texture now
3385         if (!skinframe)
3386                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3387         textureflags &= ~TEXF_FORCE_RELOAD;
3388         skinframe->stain = NULL;
3389         skinframe->merged = NULL;
3390         skinframe->base = NULL;
3391         skinframe->pants = NULL;
3392         skinframe->shirt = NULL;
3393         skinframe->nmap = NULL;
3394         skinframe->gloss = NULL;
3395         skinframe->glow = NULL;
3396         skinframe->fog = NULL;
3397         skinframe->reflect = NULL;
3398         skinframe->hasalpha = false;
3399
3400         if (ddsbase)
3401         {
3402                 skinframe->base = ddsbase;
3403                 skinframe->hasalpha = ddshasalpha;
3404                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3405                 if (r_loadfog && skinframe->hasalpha)
3406                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3407                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3408         }
3409         else
3410         {
3411                 basepixels_width = image_width;
3412                 basepixels_height = image_height;
3413                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3414                 if (textureflags & TEXF_ALPHA)
3415                 {
3416                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3417                         {
3418                                 if (basepixels[j] < 255)
3419                                 {
3420                                         skinframe->hasalpha = true;
3421                                         break;
3422                                 }
3423                         }
3424                         if (r_loadfog && skinframe->hasalpha)
3425                         {
3426                                 // has transparent pixels
3427                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3428                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3429                                 {
3430                                         pixels[j+0] = 255;
3431                                         pixels[j+1] = 255;
3432                                         pixels[j+2] = 255;
3433                                         pixels[j+3] = basepixels[j+3];
3434                                 }
3435                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3436                                 Mem_Free(pixels);
3437                         }
3438                 }
3439                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3440 #ifndef USE_GLES2
3441                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3442                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3443                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3444                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3445                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3446 #endif
3447         }
3448
3449         if (r_loaddds)
3450         {
3451                 mymiplevel = savemiplevel;
3452                 if (r_loadnormalmap)
3453                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3454                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3455                 if (r_loadgloss)
3456                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3457                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3458                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3459                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3460         }
3461
3462         // _norm is the name used by tenebrae and has been adopted as standard
3463         if (r_loadnormalmap && skinframe->nmap == NULL)
3464         {
3465                 mymiplevel = savemiplevel;
3466                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3467                 {
3468                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3469                         Mem_Free(pixels);
3470                         pixels = NULL;
3471                 }
3472                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3473                 {
3474                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3475                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3476                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3477                         Mem_Free(pixels);
3478                         Mem_Free(bumppixels);
3479                 }
3480                 else if (r_shadow_bumpscale_basetexture.value > 0)
3481                 {
3482                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3483                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3484                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3485                         Mem_Free(pixels);
3486                 }
3487 #ifndef USE_GLES2
3488                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3489                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3490 #endif
3491         }
3492
3493         // _luma is supported only for tenebrae compatibility
3494         // _glow is the preferred name
3495         mymiplevel = savemiplevel;
3496         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3497         {
3498                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3499 #ifndef USE_GLES2
3500                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3501                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3502 #endif
3503                 Mem_Free(pixels);pixels = NULL;
3504         }
3505
3506         mymiplevel = savemiplevel;
3507         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3508         {
3509                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3510 #ifndef USE_GLES2
3511                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3512                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3513 #endif
3514                 Mem_Free(pixels);
3515                 pixels = NULL;
3516         }
3517
3518         mymiplevel = savemiplevel;
3519         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3520         {
3521                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3522 #ifndef USE_GLES2
3523                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3524                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3525 #endif
3526                 Mem_Free(pixels);
3527                 pixels = NULL;
3528         }
3529
3530         mymiplevel = savemiplevel;
3531         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3532         {
3533                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3534 #ifndef USE_GLES2
3535                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3536                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3537 #endif
3538                 Mem_Free(pixels);
3539                 pixels = NULL;
3540         }
3541
3542         mymiplevel = savemiplevel;
3543         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3544         {
3545                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3546 #ifndef USE_GLES2
3547                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3548                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3549 #endif
3550                 Mem_Free(pixels);
3551                 pixels = NULL;
3552         }
3553
3554         if (basepixels)
3555                 Mem_Free(basepixels);
3556
3557         return skinframe;
3558 }
3559
3560 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3561 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3562 {
3563         int i;
3564         unsigned char *temp1, *temp2;
3565         skinframe_t *skinframe;
3566         char vabuf[1024];
3567
3568         if (cls.state == ca_dedicated)
3569                 return NULL;
3570
3571         // if already loaded just return it, otherwise make a new skinframe
3572         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3573         if (skinframe->base)
3574                 return skinframe;
3575         textureflags &= ~TEXF_FORCE_RELOAD;
3576
3577         skinframe->stain = NULL;
3578         skinframe->merged = NULL;
3579         skinframe->base = NULL;
3580         skinframe->pants = NULL;
3581         skinframe->shirt = NULL;
3582         skinframe->nmap = NULL;
3583         skinframe->gloss = NULL;
3584         skinframe->glow = NULL;
3585         skinframe->fog = NULL;
3586         skinframe->reflect = NULL;
3587         skinframe->hasalpha = false;
3588
3589         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3590         if (!skindata)
3591                 return NULL;
3592
3593         if (developer_loading.integer)
3594                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3595
3596         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3597         {
3598                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3599                 temp2 = temp1 + width * height * 4;
3600                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3601                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3602                 Mem_Free(temp1);
3603         }
3604         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3605         if (textureflags & TEXF_ALPHA)
3606         {
3607                 for (i = 3;i < width * height * 4;i += 4)
3608                 {
3609                         if (skindata[i] < 255)
3610                         {
3611                                 skinframe->hasalpha = true;
3612                                 break;
3613                         }
3614                 }
3615                 if (r_loadfog && skinframe->hasalpha)
3616                 {
3617                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3618                         memcpy(fogpixels, skindata, width * height * 4);
3619                         for (i = 0;i < width * height * 4;i += 4)
3620                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3621                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3622                         Mem_Free(fogpixels);
3623                 }
3624         }
3625
3626         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3627         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3628
3629         return skinframe;
3630 }
3631
3632 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3633 {
3634         int i;
3635         int featuresmask;
3636         skinframe_t *skinframe;
3637
3638         if (cls.state == ca_dedicated)
3639                 return NULL;
3640
3641         // if already loaded just return it, otherwise make a new skinframe
3642         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3643         if (skinframe->base)
3644                 return skinframe;
3645         //textureflags &= ~TEXF_FORCE_RELOAD;
3646
3647         skinframe->stain = NULL;
3648         skinframe->merged = NULL;
3649         skinframe->base = NULL;
3650         skinframe->pants = NULL;
3651         skinframe->shirt = NULL;
3652         skinframe->nmap = NULL;
3653         skinframe->gloss = NULL;
3654         skinframe->glow = NULL;
3655         skinframe->fog = NULL;
3656         skinframe->reflect = NULL;
3657         skinframe->hasalpha = false;
3658
3659         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3660         if (!skindata)
3661                 return NULL;
3662
3663         if (developer_loading.integer)
3664                 Con_Printf("loading quake skin \"%s\"\n", name);
3665
3666         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3667         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3668         memcpy(skinframe->qpixels, skindata, width*height);
3669         skinframe->qwidth = width;
3670         skinframe->qheight = height;
3671
3672         featuresmask = 0;
3673         for (i = 0;i < width * height;i++)
3674                 featuresmask |= palette_featureflags[skindata[i]];
3675
3676         skinframe->hasalpha = false;
3677         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3678         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3679         skinframe->qgeneratemerged = true;
3680         skinframe->qgeneratebase = skinframe->qhascolormapping;
3681         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3682
3683         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3684         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3685
3686         return skinframe;
3687 }
3688
3689 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3690 {
3691         int width;
3692         int height;
3693         unsigned char *skindata;
3694         char vabuf[1024];
3695
3696         if (!skinframe->qpixels)
3697                 return;
3698
3699         if (!skinframe->qhascolormapping)
3700                 colormapped = false;
3701
3702         if (colormapped)
3703         {
3704                 if (!skinframe->qgeneratebase)
3705                         return;
3706         }
3707         else
3708         {
3709                 if (!skinframe->qgeneratemerged)
3710                         return;
3711         }
3712
3713         width = skinframe->qwidth;
3714         height = skinframe->qheight;
3715         skindata = skinframe->qpixels;
3716
3717         if (skinframe->qgeneratenmap)
3718         {
3719                 unsigned char *temp1, *temp2;
3720                 skinframe->qgeneratenmap = false;
3721                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3722                 temp2 = temp1 + width * height * 4;
3723                 // use either a custom palette or the quake palette
3724                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3725                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3726                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3727                 Mem_Free(temp1);
3728         }
3729
3730         if (skinframe->qgenerateglow)
3731         {
3732                 skinframe->qgenerateglow = false;
3733                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3734         }
3735
3736         if (colormapped)
3737         {
3738                 skinframe->qgeneratebase = false;
3739                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3740                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3741                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3742         }
3743         else
3744         {
3745                 skinframe->qgeneratemerged = false;
3746                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3747         }
3748
3749         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3750         {
3751                 Mem_Free(skinframe->qpixels);
3752                 skinframe->qpixels = NULL;
3753         }
3754 }
3755
3756 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3757 {
3758         int i;
3759         skinframe_t *skinframe;
3760         char vabuf[1024];
3761
3762         if (cls.state == ca_dedicated)
3763                 return NULL;
3764
3765         // if already loaded just return it, otherwise make a new skinframe
3766         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3767         if (skinframe->base)
3768                 return skinframe;
3769         textureflags &= ~TEXF_FORCE_RELOAD;
3770
3771         skinframe->stain = NULL;
3772         skinframe->merged = NULL;
3773         skinframe->base = NULL;
3774         skinframe->pants = NULL;
3775         skinframe->shirt = NULL;
3776         skinframe->nmap = NULL;
3777         skinframe->gloss = NULL;
3778         skinframe->glow = NULL;
3779         skinframe->fog = NULL;
3780         skinframe->reflect = NULL;
3781         skinframe->hasalpha = false;
3782
3783         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3784         if (!skindata)
3785                 return NULL;
3786
3787         if (developer_loading.integer)
3788                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3789
3790         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3791         if (textureflags & TEXF_ALPHA)
3792         {
3793                 for (i = 0;i < width * height;i++)
3794                 {
3795                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3796                         {
3797                                 skinframe->hasalpha = true;
3798                                 break;
3799                         }
3800                 }
3801                 if (r_loadfog && skinframe->hasalpha)
3802                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3803         }
3804
3805         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3806         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3807
3808         return skinframe;
3809 }
3810
3811 skinframe_t *R_SkinFrame_LoadMissing(void)
3812 {
3813         skinframe_t *skinframe;
3814
3815         if (cls.state == ca_dedicated)
3816                 return NULL;
3817
3818         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3819         skinframe->stain = NULL;
3820         skinframe->merged = NULL;
3821         skinframe->base = NULL;
3822         skinframe->pants = NULL;
3823         skinframe->shirt = NULL;
3824         skinframe->nmap = NULL;
3825         skinframe->gloss = NULL;
3826         skinframe->glow = NULL;
3827         skinframe->fog = NULL;
3828         skinframe->reflect = NULL;
3829         skinframe->hasalpha = false;
3830
3831         skinframe->avgcolor[0] = rand() / RAND_MAX;
3832         skinframe->avgcolor[1] = rand() / RAND_MAX;
3833         skinframe->avgcolor[2] = rand() / RAND_MAX;
3834         skinframe->avgcolor[3] = 1;
3835
3836         return skinframe;
3837 }
3838
3839 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3840 typedef struct suffixinfo_s
3841 {
3842         const char *suffix;
3843         qboolean flipx, flipy, flipdiagonal;
3844 }
3845 suffixinfo_t;
3846 static suffixinfo_t suffix[3][6] =
3847 {
3848         {
3849                 {"px",   false, false, false},
3850                 {"nx",   false, false, false},
3851                 {"py",   false, false, false},
3852                 {"ny",   false, false, false},
3853                 {"pz",   false, false, false},
3854                 {"nz",   false, false, false}
3855         },
3856         {
3857                 {"posx", false, false, false},
3858                 {"negx", false, false, false},
3859                 {"posy", false, false, false},
3860                 {"negy", false, false, false},
3861                 {"posz", false, false, false},
3862                 {"negz", false, false, false}
3863         },
3864         {
3865                 {"rt",    true, false,  true},
3866                 {"lf",   false,  true,  true},
3867                 {"ft",    true,  true, false},
3868                 {"bk",   false, false, false},
3869                 {"up",    true, false,  true},
3870                 {"dn",    true, false,  true}
3871         }
3872 };
3873
3874 static int componentorder[4] = {0, 1, 2, 3};
3875
3876 static rtexture_t *R_LoadCubemap(const char *basename)
3877 {
3878         int i, j, cubemapsize;
3879         unsigned char *cubemappixels, *image_buffer;
3880         rtexture_t *cubemaptexture;
3881         char name[256];
3882         // must start 0 so the first loadimagepixels has no requested width/height
3883         cubemapsize = 0;
3884         cubemappixels = NULL;
3885         cubemaptexture = NULL;
3886         // keep trying different suffix groups (posx, px, rt) until one loads
3887         for (j = 0;j < 3 && !cubemappixels;j++)
3888         {
3889                 // load the 6 images in the suffix group
3890                 for (i = 0;i < 6;i++)
3891                 {
3892                         // generate an image name based on the base and and suffix
3893                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3894                         // load it
3895                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3896                         {
3897                                 // an image loaded, make sure width and height are equal
3898                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3899                                 {
3900                                         // if this is the first image to load successfully, allocate the cubemap memory
3901                                         if (!cubemappixels && image_width >= 1)
3902                                         {
3903                                                 cubemapsize = image_width;
3904                                                 // note this clears to black, so unavailable sides are black
3905                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3906                                         }
3907                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3908                                         if (cubemappixels)
3909                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3910                                 }
3911                                 else
3912                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3913                                 // free the image
3914                                 Mem_Free(image_buffer);
3915                         }
3916                 }
3917         }
3918         // if a cubemap loaded, upload it
3919         if (cubemappixels)
3920         {
3921                 if (developer_loading.integer)
3922                         Con_Printf("loading cubemap \"%s\"\n", basename);
3923
3924                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3925                 Mem_Free(cubemappixels);
3926         }
3927         else
3928         {
3929                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3930                 if (developer_loading.integer)
3931                 {
3932                         Con_Printf("(tried tried images ");
3933                         for (j = 0;j < 3;j++)
3934                                 for (i = 0;i < 6;i++)
3935                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3936                         Con_Print(" and was unable to find any of them).\n");
3937                 }
3938         }
3939         return cubemaptexture;
3940 }
3941
3942 rtexture_t *R_GetCubemap(const char *basename)
3943 {
3944         int i;
3945         for (i = 0;i < r_texture_numcubemaps;i++)
3946                 if (r_texture_cubemaps[i] != NULL)
3947                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3948                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3949         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3950                 return r_texture_whitecube;
3951         r_texture_numcubemaps++;
3952         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3953         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3954         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3955         return r_texture_cubemaps[i]->texture;
3956 }
3957
3958 static void R_Main_FreeViewCache(void)
3959 {
3960         if (r_refdef.viewcache.entityvisible)
3961                 Mem_Free(r_refdef.viewcache.entityvisible);
3962         if (r_refdef.viewcache.world_pvsbits)
3963                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3964         if (r_refdef.viewcache.world_leafvisible)
3965                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3966         if (r_refdef.viewcache.world_surfacevisible)
3967                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3968         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3969 }
3970
3971 static void R_Main_ResizeViewCache(void)
3972 {
3973         int numentities = r_refdef.scene.numentities;
3974         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3975         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3976         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3977         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3978         if (r_refdef.viewcache.maxentities < numentities)
3979         {
3980                 r_refdef.viewcache.maxentities = numentities;
3981                 if (r_refdef.viewcache.entityvisible)
3982                         Mem_Free(r_refdef.viewcache.entityvisible);
3983                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3984         }
3985         if (r_refdef.viewcache.world_numclusters != numclusters)
3986         {
3987                 r_refdef.viewcache.world_numclusters = numclusters;
3988                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3989                 if (r_refdef.viewcache.world_pvsbits)
3990                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3991                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3992         }
3993         if (r_refdef.viewcache.world_numleafs != numleafs)
3994         {
3995                 r_refdef.viewcache.world_numleafs = numleafs;
3996                 if (r_refdef.viewcache.world_leafvisible)
3997                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3998                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3999         }
4000         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4001         {
4002                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4003                 if (r_refdef.viewcache.world_surfacevisible)
4004                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4005                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4006         }
4007 }
4008
4009 extern rtexture_t *loadingscreentexture;
4010 static void gl_main_start(void)
4011 {
4012         loadingscreentexture = NULL;
4013         r_texture_blanknormalmap = NULL;
4014         r_texture_white = NULL;
4015         r_texture_grey128 = NULL;
4016         r_texture_black = NULL;
4017         r_texture_whitecube = NULL;
4018         r_texture_normalizationcube = NULL;
4019         r_texture_fogattenuation = NULL;
4020         r_texture_fogheighttexture = NULL;
4021         r_texture_gammaramps = NULL;
4022         r_texture_numcubemaps = 0;
4023         r_uniformbufferalignment = 32;
4024
4025         r_loaddds = r_texture_dds_load.integer != 0;
4026         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4027
4028         switch(vid.renderpath)
4029         {
4030         case RENDERPATH_GL20:
4031         case RENDERPATH_D3D9:
4032         case RENDERPATH_D3D10:
4033         case RENDERPATH_D3D11:
4034         case RENDERPATH_SOFT:
4035         case RENDERPATH_GLES2:
4036                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4037                 Cvar_SetValueQuick(&gl_combine, 1);
4038                 Cvar_SetValueQuick(&r_glsl, 1);
4039                 r_loadnormalmap = true;
4040                 r_loadgloss = true;
4041                 r_loadfog = false;
4042 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4043                 if (vid.support.arb_uniform_buffer_object)
4044                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4045 #endif
4046                         break;
4047         case RENDERPATH_GL13:
4048         case RENDERPATH_GLES1:
4049                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4050                 Cvar_SetValueQuick(&gl_combine, 1);
4051                 Cvar_SetValueQuick(&r_glsl, 0);
4052                 r_loadnormalmap = false;
4053                 r_loadgloss = false;
4054                 r_loadfog = true;
4055                 break;
4056         case RENDERPATH_GL11:
4057                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4058                 Cvar_SetValueQuick(&gl_combine, 0);
4059                 Cvar_SetValueQuick(&r_glsl, 0);
4060                 r_loadnormalmap = false;
4061                 r_loadgloss = false;
4062                 r_loadfog = true;
4063                 break;
4064         }
4065
4066         R_AnimCache_Free();
4067         R_FrameData_Reset();
4068         R_BufferData_Reset();
4069
4070         r_numqueries = 0;
4071         r_maxqueries = 0;
4072         memset(r_queries, 0, sizeof(r_queries));
4073
4074         r_qwskincache = NULL;
4075         r_qwskincache_size = 0;
4076
4077         // due to caching of texture_t references, the collision cache must be reset
4078         Collision_Cache_Reset(true);
4079
4080         // set up r_skinframe loading system for textures
4081         memset(&r_skinframe, 0, sizeof(r_skinframe));
4082         r_skinframe.loadsequence = 1;
4083         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4084
4085         r_main_texturepool = R_AllocTexturePool();
4086         R_BuildBlankTextures();
4087         R_BuildNoTexture();
4088         if (vid.support.arb_texture_cube_map)
4089         {
4090                 R_BuildWhiteCube();
4091                 R_BuildNormalizationCube();
4092         }
4093         r_texture_fogattenuation = NULL;
4094         r_texture_fogheighttexture = NULL;
4095         r_texture_gammaramps = NULL;
4096         //r_texture_fogintensity = NULL;
4097         memset(&r_fb, 0, sizeof(r_fb));
4098         r_glsl_permutation = NULL;
4099         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4100         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4101         glslshaderstring = NULL;
4102 #ifdef SUPPORTD3D
4103         r_hlsl_permutation = NULL;
4104         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4105         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4106 #endif
4107         hlslshaderstring = NULL;
4108         memset(&r_svbsp, 0, sizeof (r_svbsp));
4109
4110         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4111         r_texture_numcubemaps = 0;
4112
4113         r_refdef.fogmasktable_density = 0;
4114
4115 #ifdef __ANDROID__
4116         // For Steelstorm Android
4117         // FIXME CACHE the program and reload
4118         // FIXME see possible combinations for SS:BR android
4119         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4120         R_SetupShader_SetPermutationGLSL(0, 12);
4121         R_SetupShader_SetPermutationGLSL(0, 13);
4122         R_SetupShader_SetPermutationGLSL(0, 8388621);
4123         R_SetupShader_SetPermutationGLSL(3, 0);
4124         R_SetupShader_SetPermutationGLSL(3, 2048);
4125         R_SetupShader_SetPermutationGLSL(5, 0);
4126         R_SetupShader_SetPermutationGLSL(5, 2);
4127         R_SetupShader_SetPermutationGLSL(5, 2048);
4128         R_SetupShader_SetPermutationGLSL(5, 8388608);
4129         R_SetupShader_SetPermutationGLSL(11, 1);
4130         R_SetupShader_SetPermutationGLSL(11, 2049);
4131         R_SetupShader_SetPermutationGLSL(11, 8193);
4132         R_SetupShader_SetPermutationGLSL(11, 10241);
4133         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4134 #endif
4135 }
4136
4137 static void gl_main_shutdown(void)
4138 {
4139         R_AnimCache_Free();
4140         R_FrameData_Reset();
4141         R_BufferData_Reset();
4142
4143         R_Main_FreeViewCache();
4144
4145         switch(vid.renderpath)
4146         {
4147         case RENDERPATH_GL11:
4148         case RENDERPATH_GL13:
4149         case RENDERPATH_GL20:
4150         case RENDERPATH_GLES1:
4151         case RENDERPATH_GLES2:
4152 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4153                 if (r_maxqueries)
4154                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4155 #endif
4156                 break;
4157         case RENDERPATH_D3D9:
4158                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4159                 break;
4160         case RENDERPATH_D3D10:
4161                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4162                 break;
4163         case RENDERPATH_D3D11:
4164                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4165                 break;
4166         case RENDERPATH_SOFT:
4167                 break;
4168         }
4169
4170         r_numqueries = 0;
4171         r_maxqueries = 0;
4172         memset(r_queries, 0, sizeof(r_queries));
4173
4174         r_qwskincache = NULL;
4175         r_qwskincache_size = 0;
4176
4177         // clear out the r_skinframe state
4178         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4179         memset(&r_skinframe, 0, sizeof(r_skinframe));
4180
4181         if (r_svbsp.nodes)
4182                 Mem_Free(r_svbsp.nodes);
4183         memset(&r_svbsp, 0, sizeof (r_svbsp));
4184         R_FreeTexturePool(&r_main_texturepool);
4185         loadingscreentexture = NULL;
4186         r_texture_blanknormalmap = NULL;
4187         r_texture_white = NULL;
4188         r_texture_grey128 = NULL;
4189         r_texture_black = NULL;
4190         r_texture_whitecube = NULL;
4191         r_texture_normalizationcube = NULL;
4192         r_texture_fogattenuation = NULL;
4193         r_texture_fogheighttexture = NULL;
4194         r_texture_gammaramps = NULL;
4195         r_texture_numcubemaps = 0;
4196         //r_texture_fogintensity = NULL;
4197         memset(&r_fb, 0, sizeof(r_fb));
4198         R_GLSL_Restart_f();
4199
4200         r_glsl_permutation = NULL;
4201         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4202         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4203         glslshaderstring = NULL;
4204 #ifdef SUPPORTD3D
4205         r_hlsl_permutation = NULL;
4206         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4207         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4208 #endif
4209         hlslshaderstring = NULL;
4210 }
4211
4212 static void gl_main_newmap(void)
4213 {
4214         // FIXME: move this code to client
4215         char *entities, entname[MAX_QPATH];
4216         if (r_qwskincache)
4217                 Mem_Free(r_qwskincache);
4218         r_qwskincache = NULL;
4219         r_qwskincache_size = 0;
4220         if (cl.worldmodel)
4221         {
4222                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4223                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4224                 {
4225                         CL_ParseEntityLump(entities);
4226                         Mem_Free(entities);
4227                         return;
4228                 }
4229                 if (cl.worldmodel->brush.entities)
4230                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4231         }
4232         R_Main_FreeViewCache();
4233
4234         R_FrameData_Reset();
4235         R_BufferData_Reset();
4236 }
4237
4238 void GL_Main_Init(void)
4239 {
4240         int i;
4241         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4242
4243         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4244         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4245         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4246         if (gamemode == GAME_NEHAHRA)
4247         {
4248                 Cvar_RegisterVariable (&gl_fogenable);
4249                 Cvar_RegisterVariable (&gl_fogdensity);
4250                 Cvar_RegisterVariable (&gl_fogred);
4251                 Cvar_RegisterVariable (&gl_foggreen);
4252                 Cvar_RegisterVariable (&gl_fogblue);
4253                 Cvar_RegisterVariable (&gl_fogstart);
4254                 Cvar_RegisterVariable (&gl_fogend);
4255                 Cvar_RegisterVariable (&gl_skyclip);
4256         }
4257         Cvar_RegisterVariable(&r_motionblur);
4258         Cvar_RegisterVariable(&r_damageblur);
4259         Cvar_RegisterVariable(&r_motionblur_averaging);
4260         Cvar_RegisterVariable(&r_motionblur_randomize);
4261         Cvar_RegisterVariable(&r_motionblur_minblur);
4262         Cvar_RegisterVariable(&r_motionblur_maxblur);
4263         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4264         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4265         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4266         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4267         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4268         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4269         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4270         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4271         Cvar_RegisterVariable(&r_equalize_entities_by);
4272         Cvar_RegisterVariable(&r_equalize_entities_to);
4273         Cvar_RegisterVariable(&r_depthfirst);
4274         Cvar_RegisterVariable(&r_useinfinitefarclip);
4275         Cvar_RegisterVariable(&r_farclip_base);
4276         Cvar_RegisterVariable(&r_farclip_world);
4277         Cvar_RegisterVariable(&r_nearclip);
4278         Cvar_RegisterVariable(&r_deformvertexes);
4279         Cvar_RegisterVariable(&r_transparent);
4280         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4281         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4282         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4283         Cvar_RegisterVariable(&r_showoverdraw);
4284         Cvar_RegisterVariable(&r_showbboxes);
4285         Cvar_RegisterVariable(&r_showsurfaces);
4286         Cvar_RegisterVariable(&r_showtris);
4287         Cvar_RegisterVariable(&r_shownormals);
4288         Cvar_RegisterVariable(&r_showlighting);
4289         Cvar_RegisterVariable(&r_showshadowvolumes);
4290         Cvar_RegisterVariable(&r_showcollisionbrushes);
4291         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4292         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4293         Cvar_RegisterVariable(&r_showdisabledepthtest);
4294         Cvar_RegisterVariable(&r_drawportals);
4295         Cvar_RegisterVariable(&r_drawentities);
4296         Cvar_RegisterVariable(&r_draw2d);
4297         Cvar_RegisterVariable(&r_drawworld);
4298         Cvar_RegisterVariable(&r_cullentities_trace);
4299         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4300         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4301         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4302         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4303         Cvar_RegisterVariable(&r_sortentities);
4304         Cvar_RegisterVariable(&r_drawviewmodel);
4305         Cvar_RegisterVariable(&r_drawexteriormodel);
4306         Cvar_RegisterVariable(&r_speeds);
4307         Cvar_RegisterVariable(&r_fullbrights);
4308         Cvar_RegisterVariable(&r_wateralpha);
4309         Cvar_RegisterVariable(&r_dynamic);
4310         Cvar_RegisterVariable(&r_fakelight);
4311         Cvar_RegisterVariable(&r_fakelight_intensity);
4312         Cvar_RegisterVariable(&r_fullbright);
4313         Cvar_RegisterVariable(&r_shadows);
4314         Cvar_RegisterVariable(&r_shadows_darken);
4315         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4316         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4317         Cvar_RegisterVariable(&r_shadows_throwdistance);
4318         Cvar_RegisterVariable(&r_shadows_throwdirection);
4319         Cvar_RegisterVariable(&r_shadows_focus);
4320         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4321         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4322         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4323         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4324         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4325         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4326         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4327         Cvar_RegisterVariable(&r_fog_exp2);
4328         Cvar_RegisterVariable(&r_fog_clear);
4329         Cvar_RegisterVariable(&r_drawfog);
4330         Cvar_RegisterVariable(&r_transparentdepthmasking);
4331         Cvar_RegisterVariable(&r_transparent_sortmindist);
4332         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4333         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4334         Cvar_RegisterVariable(&r_texture_dds_load);
4335         Cvar_RegisterVariable(&r_texture_dds_save);
4336         Cvar_RegisterVariable(&r_textureunits);
4337         Cvar_RegisterVariable(&gl_combine);
4338         Cvar_RegisterVariable(&r_usedepthtextures);
4339         Cvar_RegisterVariable(&r_viewfbo);
4340         Cvar_RegisterVariable(&r_viewscale);
4341         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4342         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4343         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4344         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4345         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4346         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4347         Cvar_RegisterVariable(&r_glsl);
4348         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4349         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4350         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4351         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4352         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4353         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4354         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4355         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4356         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4357         Cvar_RegisterVariable(&r_glsl_postprocess);
4358         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4359         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4360         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4361         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4362         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4363         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4364         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4365         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4366         Cvar_RegisterVariable(&r_celshading);
4367         Cvar_RegisterVariable(&r_celoutlines);
4368
4369         Cvar_RegisterVariable(&r_water);
4370         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4371         Cvar_RegisterVariable(&r_water_clippingplanebias);
4372         Cvar_RegisterVariable(&r_water_refractdistort);
4373         Cvar_RegisterVariable(&r_water_reflectdistort);
4374         Cvar_RegisterVariable(&r_water_scissormode);
4375         Cvar_RegisterVariable(&r_water_lowquality);
4376         Cvar_RegisterVariable(&r_water_hideplayer);
4377         Cvar_RegisterVariable(&r_water_fbo);
4378
4379         Cvar_RegisterVariable(&r_lerpsprites);
4380         Cvar_RegisterVariable(&r_lerpmodels);
4381         Cvar_RegisterVariable(&r_lerplightstyles);
4382         Cvar_RegisterVariable(&r_waterscroll);
4383         Cvar_RegisterVariable(&r_bloom);
4384         Cvar_RegisterVariable(&r_bloom_colorscale);
4385         Cvar_RegisterVariable(&r_bloom_brighten);
4386         Cvar_RegisterVariable(&r_bloom_blur);
4387         Cvar_RegisterVariable(&r_bloom_resolution);
4388         Cvar_RegisterVariable(&r_bloom_colorexponent);
4389         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4390         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4391         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4392         Cvar_RegisterVariable(&r_hdr_glowintensity);
4393         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4394         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4395         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4396         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4397         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4398         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4399         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4400         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4401         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4402         Cvar_RegisterVariable(&developer_texturelogging);
4403         Cvar_RegisterVariable(&gl_lightmaps);
4404         Cvar_RegisterVariable(&r_test);
4405         Cvar_RegisterVariable(&r_batch_multidraw);
4406         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4407         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4408         Cvar_RegisterVariable(&r_glsl_skeletal);
4409         Cvar_RegisterVariable(&r_glsl_saturation);
4410         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4411         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4412         Cvar_RegisterVariable(&r_framedatasize);
4413         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4414                 Cvar_RegisterVariable(&r_buffermegs[i]);
4415         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4416         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4417                 Cvar_SetValue("r_fullbrights", 0);
4418 #ifdef DP_MOBILETOUCH
4419         // GLES devices have terrible depth precision in general, so...
4420         Cvar_SetValueQuick(&r_nearclip, 4);
4421         Cvar_SetValueQuick(&r_farclip_base, 4096);
4422         Cvar_SetValueQuick(&r_farclip_world, 0);
4423         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4424 #endif
4425         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4426 }
4427
4428 void Render_Init(void)
4429 {
4430         gl_backend_init();
4431         R_Textures_Init();
4432         GL_Main_Init();
4433         Font_Init();
4434         GL_Draw_Init();
4435         R_Shadow_Init();
4436         R_Sky_Init();
4437         GL_Surf_Init();
4438         Sbar_Init();
4439         R_Particles_Init();
4440         R_Explosion_Init();
4441         R_LightningBeams_Init();
4442         Mod_RenderInit();
4443 }
4444
4445 /*
4446 ===============
4447 GL_Init
4448 ===============
4449 */
4450 #ifndef USE_GLES2
4451 extern char *ENGINE_EXTENSIONS;
4452 void GL_Init (void)
4453 {
4454         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4455         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4456         gl_version = (const char *)qglGetString(GL_VERSION);
4457         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4458
4459         if (!gl_extensions)
4460                 gl_extensions = "";
4461         if (!gl_platformextensions)
4462                 gl_platformextensions = "";
4463
4464         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4465         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4466         Con_Printf("GL_VERSION: %s\n", gl_version);
4467         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4468         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4469
4470         VID_CheckExtensions();
4471
4472         // LordHavoc: report supported extensions
4473         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4474
4475         // clear to black (loading plaque will be seen over this)
4476         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4477 }
4478 #endif
4479
4480 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4481 {
4482         int i;
4483         mplane_t *p;
4484         if (r_trippy.integer)
4485                 return false;
4486         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4487         {
4488                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4489                 if (i == 4)
4490                         continue;
4491                 p = r_refdef.view.frustum + i;
4492                 switch(p->signbits)
4493                 {
4494                 default:
4495                 case 0:
4496                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4497                                 return true;
4498                         break;
4499                 case 1:
4500                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4501                                 return true;
4502                         break;
4503                 case 2:
4504                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4505                                 return true;
4506                         break;
4507                 case 3:
4508                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4509                                 return true;
4510                         break;
4511                 case 4:
4512                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4513                                 return true;
4514                         break;
4515                 case 5:
4516                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4517                                 return true;
4518                         break;
4519                 case 6:
4520                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4521                                 return true;
4522                         break;
4523                 case 7:
4524                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4525                                 return true;
4526                         break;
4527                 }
4528         }
4529         return false;
4530 }
4531
4532 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4533 {
4534         int i;
4535         const mplane_t *p;
4536         if (r_trippy.integer)
4537                 return false;
4538         for (i = 0;i < numplanes;i++)
4539         {
4540                 p = planes + i;
4541                 switch(p->signbits)
4542                 {
4543                 default:
4544                 case 0:
4545                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4546                                 return true;
4547                         break;
4548                 case 1:
4549                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4550                                 return true;
4551                         break;
4552                 case 2:
4553                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4554                                 return true;
4555                         break;
4556                 case 3:
4557                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4558                                 return true;
4559                         break;
4560                 case 4:
4561                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4562                                 return true;
4563                         break;
4564                 case 5:
4565                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4566                                 return true;
4567                         break;
4568                 case 6:
4569                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4570                                 return true;
4571                         break;
4572                 case 7:
4573                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4574                                 return true;
4575                         break;
4576                 }
4577         }
4578         return false;
4579 }
4580
4581 //==================================================================================
4582
4583 // LordHavoc: this stores temporary data used within the same frame
4584
4585 typedef struct r_framedata_mem_s
4586 {
4587         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4588         size_t size; // how much usable space
4589         size_t current; // how much space in use
4590         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4591         size_t wantedsize; // how much space was allocated
4592         unsigned char *data; // start of real data (16byte aligned)
4593 }
4594 r_framedata_mem_t;
4595
4596 static r_framedata_mem_t *r_framedata_mem;
4597
4598 void R_FrameData_Reset(void)
4599 {
4600         while (r_framedata_mem)
4601         {
4602                 r_framedata_mem_t *next = r_framedata_mem->purge;
4603                 Mem_Free(r_framedata_mem);
4604                 r_framedata_mem = next;
4605         }
4606 }
4607
4608 static void R_FrameData_Resize(qboolean mustgrow)
4609 {
4610         size_t wantedsize;
4611         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4612         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4613         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4614         {
4615                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4616                 newmem->wantedsize = wantedsize;
4617                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4618                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4619                 newmem->current = 0;
4620                 newmem->mark = 0;
4621                 newmem->purge = r_framedata_mem;
4622                 r_framedata_mem = newmem;
4623         }
4624 }
4625
4626 void R_FrameData_NewFrame(void)
4627 {
4628         R_FrameData_Resize(false);
4629         if (!r_framedata_mem)
4630                 return;
4631         // if we ran out of space on the last frame, free the old memory now
4632         while (r_framedata_mem->purge)
4633         {
4634                 // repeatedly remove the second item in the list, leaving only head
4635                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4636                 Mem_Free(r_framedata_mem->purge);
4637                 r_framedata_mem->purge = next;
4638         }
4639         // reset the current mem pointer
4640         r_framedata_mem->current = 0;
4641         r_framedata_mem->mark = 0;
4642 }
4643
4644 void *R_FrameData_Alloc(size_t size)
4645 {
4646         void *data;
4647         float newvalue;
4648
4649         // align to 16 byte boundary - the data pointer is already aligned, so we
4650         // only need to ensure the size of every allocation is also aligned
4651         size = (size + 15) & ~15;
4652
4653         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4654         {
4655                 // emergency - we ran out of space, allocate more memory
4656                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4657                 // this might not be a growing it, but we'll allocate another buffer every time
4658                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4659                 R_FrameData_Resize(true);
4660         }
4661
4662         data = r_framedata_mem->data + r_framedata_mem->current;
4663         r_framedata_mem->current += size;
4664
4665         // count the usage for stats
4666         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4667         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4668
4669         return (void *)data;
4670 }
4671
4672 void *R_FrameData_Store(size_t size, void *data)
4673 {
4674         void *d = R_FrameData_Alloc(size);
4675         if (d && data)
4676                 memcpy(d, data, size);
4677         return d;
4678 }
4679
4680 void R_FrameData_SetMark(void)
4681 {
4682         if (!r_framedata_mem)
4683                 return;
4684         r_framedata_mem->mark = r_framedata_mem->current;
4685 }
4686
4687 void R_FrameData_ReturnToMark(void)
4688 {
4689         if (!r_framedata_mem)
4690                 return;
4691         r_framedata_mem->current = r_framedata_mem->mark;
4692 }
4693
4694 //==================================================================================
4695
4696 // avoid reusing the same buffer objects on consecutive frames
4697 #define R_BUFFERDATA_CYCLE 3
4698
4699 typedef struct r_bufferdata_buffer_s
4700 {
4701         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4702         size_t size; // how much usable space
4703         size_t current; // how much space in use
4704         r_meshbuffer_t *buffer; // the buffer itself
4705 }
4706 r_bufferdata_buffer_t;
4707
4708 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4709 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4710
4711 /// frees all dynamic buffers
4712 void R_BufferData_Reset(void)
4713 {
4714         int cycle, type;
4715         r_bufferdata_buffer_t **p, *mem;
4716         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4717         {
4718                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4719                 {
4720                         // free all buffers
4721                         p = &r_bufferdata_buffer[cycle][type];
4722                         while (*p)
4723                         {
4724                                 mem = *p;
4725                                 *p = (*p)->purge;
4726                                 if (mem->buffer)
4727                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4728                                 Mem_Free(mem);
4729                         }
4730                 }
4731         }
4732 }
4733
4734 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4735 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4736 {
4737         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4738         size_t size;
4739         float newvalue = r_buffermegs[type].value;
4740
4741         // increase the cvar if we have to (but only if we already have a mem)
4742         if (mustgrow && mem)
4743                 newvalue *= 2.0f;
4744         newvalue = bound(0.25f, newvalue, 256.0f);
4745         while (newvalue * 1024*1024 < minsize)
4746                 newvalue *= 2.0f;
4747
4748         // clamp the cvar to valid range
4749         newvalue = bound(0.25f, newvalue, 256.0f);
4750         if (r_buffermegs[type].value != newvalue)
4751                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4752
4753         // calculate size in bytes
4754         size = (size_t)(newvalue * 1024*1024);
4755         size = bound(131072, size, 256*1024*1024);
4756
4757         // allocate a new buffer if the size is different (purge old one later)
4758         // or if we were told we must grow the buffer
4759         if (!mem || mem->size != size || mustgrow)
4760         {
4761                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4762                 mem->size = size;
4763                 mem->current = 0;
4764                 if (type == R_BUFFERDATA_VERTEX)
4765                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4766                 else if (type == R_BUFFERDATA_INDEX16)
4767                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4768                 else if (type == R_BUFFERDATA_INDEX32)
4769                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4770                 else if (type == R_BUFFERDATA_UNIFORM)
4771                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4772                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4773                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4774         }
4775 }
4776
4777 void R_BufferData_NewFrame(void)
4778 {
4779         int type;
4780         r_bufferdata_buffer_t **p, *mem;
4781         // cycle to the next frame's buffers
4782         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4783         // if we ran out of space on the last time we used these buffers, free the old memory now
4784         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4785         {
4786                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4787                 {
4788                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4789                         // free all but the head buffer, this is how we recycle obsolete
4790                         // buffers after they are no longer in use
4791                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4792                         while (*p)
4793                         {
4794                                 mem = *p;
4795                                 *p = (*p)->purge;
4796                                 if (mem->buffer)
4797                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4798                                 Mem_Free(mem);
4799                         }
4800                         // reset the current offset
4801                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4802                 }
4803         }
4804 }
4805
4806 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4807 {
4808         r_bufferdata_buffer_t *mem;
4809         int offset = 0;
4810         int padsize;
4811
4812         *returnbufferoffset = 0;
4813
4814         // align size to a byte boundary appropriate for the buffer type, this
4815         // makes all allocations have aligned start offsets
4816         if (type == R_BUFFERDATA_UNIFORM)
4817                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4818         else
4819                 padsize = (datasize + 15) & ~15;
4820
4821         // if we ran out of space in this buffer we must allocate a new one
4822         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)
4823                 R_BufferData_Resize(type, true, padsize);
4824
4825         // if the resize did not give us enough memory, fail
4826         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4827                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4828
4829         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4830         offset = mem->current;
4831         mem->current += padsize;
4832
4833         // upload the data to the buffer at the chosen offset
4834         if (offset == 0)
4835                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4836         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4837
4838         // count the usage for stats
4839         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4840         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4841
4842         // return the buffer offset
4843         *returnbufferoffset = offset;
4844
4845         return mem->buffer;
4846 }
4847
4848 //==================================================================================
4849
4850 // LordHavoc: animcache originally written by Echon, rewritten since then
4851
4852 /**
4853  * Animation cache prevents re-generating mesh data for an animated model
4854  * multiple times in one frame for lighting, shadowing, reflections, etc.
4855  */
4856
4857 void R_AnimCache_Free(void)
4858 {
4859 }
4860
4861 void R_AnimCache_ClearCache(void)
4862 {
4863         int i;
4864         entity_render_t *ent;
4865
4866         for (i = 0;i < r_refdef.scene.numentities;i++)
4867         {
4868                 ent = r_refdef.scene.entities[i];
4869                 ent->animcache_vertex3f = NULL;
4870                 ent->animcache_vertex3f_vertexbuffer = NULL;
4871                 ent->animcache_vertex3f_bufferoffset = 0;
4872                 ent->animcache_normal3f = NULL;
4873                 ent->animcache_normal3f_vertexbuffer = NULL;
4874                 ent->animcache_normal3f_bufferoffset = 0;
4875                 ent->animcache_svector3f = NULL;
4876                 ent->animcache_svector3f_vertexbuffer = NULL;
4877                 ent->animcache_svector3f_bufferoffset = 0;
4878                 ent->animcache_tvector3f = NULL;
4879                 ent->animcache_tvector3f_vertexbuffer = NULL;
4880                 ent->animcache_tvector3f_bufferoffset = 0;
4881                 ent->animcache_vertexmesh = NULL;
4882                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4883                 ent->animcache_vertexmesh_bufferoffset = 0;
4884                 ent->animcache_skeletaltransform3x4 = NULL;
4885                 ent->animcache_skeletaltransform3x4buffer = NULL;
4886                 ent->animcache_skeletaltransform3x4offset = 0;
4887                 ent->animcache_skeletaltransform3x4size = 0;
4888         }
4889 }
4890
4891 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4892 {
4893         int i;
4894
4895         // check if we need the meshbuffers
4896         if (!vid.useinterleavedarrays)
4897                 return;
4898
4899         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4900                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4901         // TODO: upload vertexbuffer?
4902         if (ent->animcache_vertexmesh)
4903         {
4904                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4905                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4906                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4907                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4908                 for (i = 0;i < numvertices;i++)
4909                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4910                 if (ent->animcache_svector3f)
4911                         for (i = 0;i < numvertices;i++)
4912                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4913                 if (ent->animcache_tvector3f)
4914                         for (i = 0;i < numvertices;i++)
4915                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4916                 if (ent->animcache_normal3f)
4917                         for (i = 0;i < numvertices;i++)
4918                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4919         }
4920 }
4921
4922 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4923 {
4924         dp_model_t *model = ent->model;
4925         int numvertices;
4926
4927         // see if this ent is worth caching
4928         if (!model || !model->Draw || !model->AnimateVertices)
4929                 return false;
4930         // nothing to cache if it contains no animations and has no skeleton
4931         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4932                 return false;
4933         // see if it is already cached for gpuskeletal
4934         if (ent->animcache_skeletaltransform3x4)
4935                 return false;
4936         // see if it is already cached as a mesh
4937         if (ent->animcache_vertex3f)
4938         {
4939                 // check if we need to add normals or tangents
4940                 if (ent->animcache_normal3f)
4941                         wantnormals = false;
4942                 if (ent->animcache_svector3f)
4943                         wanttangents = false;
4944                 if (!wantnormals && !wanttangents)
4945                         return false;
4946         }
4947
4948         // check which kind of cache we need to generate
4949         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4950         {
4951                 // cache the skeleton so the vertex shader can use it
4952                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4953                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4954                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4955                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4956                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4957                 // note: this can fail if the buffer is at the grow limit
4958                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4959                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4960         }
4961         else if (ent->animcache_vertex3f)
4962         {
4963                 // mesh was already cached but we may need to add normals/tangents
4964                 // (this only happens with multiple views, reflections, cameras, etc)
4965                 if (wantnormals || wanttangents)
4966                 {
4967                         numvertices = model->surfmesh.num_vertices;
4968                         if (wantnormals)
4969                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4970                         if (wanttangents)
4971                         {
4972                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4973                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4974                         }
4975                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4976                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4977                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4978                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4979                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4980                 }
4981         }
4982         else
4983         {
4984                 // generate mesh cache
4985                 numvertices = model->surfmesh.num_vertices;
4986                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4987                 if (wantnormals)
4988                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4989                 if (wanttangents)
4990                 {
4991                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4992                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4993                 }
4994                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4995                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4996                 if (wantnormals || wanttangents)
4997                 {
4998                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4999                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5000                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5001                 }
5002                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5003                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5004                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5005         }
5006         return true;
5007 }
5008
5009 void R_AnimCache_CacheVisibleEntities(void)
5010 {
5011         int i;
5012         qboolean wantnormals = true;
5013         qboolean wanttangents = !r_showsurfaces.integer;
5014
5015         switch(vid.renderpath)
5016         {
5017         case RENDERPATH_GL20:
5018         case RENDERPATH_D3D9:
5019         case RENDERPATH_D3D10:
5020         case RENDERPATH_D3D11:
5021         case RENDERPATH_GLES2:
5022                 break;
5023         case RENDERPATH_GL11:
5024         case RENDERPATH_GL13:
5025         case RENDERPATH_GLES1:
5026                 wanttangents = false;
5027                 break;
5028         case RENDERPATH_SOFT:
5029                 break;
5030         }
5031
5032         if (r_shownormals.integer)
5033                 wanttangents = wantnormals = true;
5034
5035         // TODO: thread this
5036         // NOTE: R_PrepareRTLights() also caches entities
5037
5038         for (i = 0;i < r_refdef.scene.numentities;i++)
5039                 if (r_refdef.viewcache.entityvisible[i])
5040                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5041 }
5042
5043 //==================================================================================
5044
5045 extern cvar_t r_overheadsprites_pushback;
5046
5047 static void R_View_UpdateEntityLighting (void)
5048 {
5049         int i;
5050         entity_render_t *ent;
5051         vec3_t tempdiffusenormal, avg;
5052         vec_t f, fa, fd, fdd;
5053         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5054
5055         for (i = 0;i < r_refdef.scene.numentities;i++)
5056         {
5057                 ent = r_refdef.scene.entities[i];
5058
5059                 // skip unseen models
5060                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5061                         continue;
5062
5063                 // skip bsp models
5064                 if (ent->model && ent->model == cl.worldmodel)
5065                 {
5066                         // TODO: use modellight for r_ambient settings on world?
5067                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5068                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5069                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5070                         continue;
5071                 }
5072                 
5073                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5074                 {
5075                         // aleady updated by CSQC
5076                         // TODO: force modellight on BSP models in this case?
5077                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5078                 }
5079                 else
5080                 {
5081                         // fetch the lighting from the worldmodel data
5082                         VectorClear(ent->modellight_ambient);
5083                         VectorClear(ent->modellight_diffuse);
5084                         VectorClear(tempdiffusenormal);
5085                         if (ent->flags & RENDER_LIGHT)
5086                         {
5087                                 vec3_t org;
5088                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5089
5090                                 // complete lightning for lit sprites
5091                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5092                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5093                                 {
5094                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5095                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5096                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5097                                 }
5098                                 else
5099                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5100
5101                                 if(ent->flags & RENDER_EQUALIZE)
5102                                 {
5103                                         // first fix up ambient lighting...
5104                                         if(r_equalize_entities_minambient.value > 0)
5105                                         {
5106                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5107                                                 if(fd > 0)
5108                                                 {
5109                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5110                                                         if(fa < r_equalize_entities_minambient.value * fd)
5111                                                         {
5112                                                                 // solve:
5113                                                                 //   fa'/fd' = minambient
5114                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5115                                                                 //   ...
5116                                                                 //   fa' = fd' * minambient
5117                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5118                                                                 //   ...
5119                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5120                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5121                                                                 //   ...
5122                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5123                                                                 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
5124                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5125                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5126                                                         }
5127                                                 }
5128                                         }
5129
5130                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5131                                         {
5132                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5133                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5134                                                 f = fa + 0.25 * fd;
5135                                                 if(f > 0)
5136                                                 {
5137                                                         // adjust brightness and saturation to target
5138                                                         avg[0] = avg[1] = avg[2] = fa / f;
5139                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5140                                                         avg[0] = avg[1] = avg[2] = fd / f;
5141                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5142                                                 }
5143                                         }
5144                                 }
5145                         }
5146                         else // highly rare
5147                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5148                 }
5149
5150                 // move the light direction into modelspace coordinates for lighting code
5151                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5152                 if(VectorLength2(ent->modellight_lightdir) == 0)
5153                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5154                 VectorNormalize(ent->modellight_lightdir);
5155         }
5156 }
5157
5158 #define MAX_LINEOFSIGHTTRACES 64
5159
5160 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5161 {
5162         int i;
5163         vec3_t boxmins, boxmaxs;
5164         vec3_t start;
5165         vec3_t end;
5166         dp_model_t *model = r_refdef.scene.worldmodel;
5167
5168         if (!model || !model->brush.TraceLineOfSight)
5169                 return true;
5170
5171         // expand the box a little
5172         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5173         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5174         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5175         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5176         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5177         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5178
5179         // return true if eye is inside enlarged box
5180         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5181                 return true;
5182
5183         // try center
5184         VectorCopy(eye, start);
5185         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5186         if (model->brush.TraceLineOfSight(model, start, end))
5187                 return true;
5188
5189         // try various random positions
5190         for (i = 0;i < numsamples;i++)
5191         {
5192                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5193                 if (model->brush.TraceLineOfSight(model, start, end))
5194                         return true;
5195         }
5196
5197         return false;
5198 }
5199
5200
5201 static void R_View_UpdateEntityVisible (void)
5202 {
5203         int i;
5204         int renderimask;
5205         int samples;
5206         entity_render_t *ent;
5207
5208         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5209                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5210                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5211                 :                                                          RENDER_EXTERIORMODEL;
5212         if (!r_drawviewmodel.integer)
5213                 renderimask |= RENDER_VIEWMODEL;
5214         if (!r_drawexteriormodel.integer)
5215                 renderimask |= RENDER_EXTERIORMODEL;
5216         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5217         {
5218                 // worldmodel can check visibility
5219                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5220                 for (i = 0;i < r_refdef.scene.numentities;i++)
5221                 {
5222                         ent = r_refdef.scene.entities[i];
5223                         if (!(ent->flags & renderimask))
5224                         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)))
5225                         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))
5226                                 r_refdef.viewcache.entityvisible[i] = true;
5227                 }
5228         }
5229         else
5230         {
5231                 // no worldmodel or it can't check visibility
5232                 for (i = 0;i < r_refdef.scene.numentities;i++)
5233                 {
5234                         ent = r_refdef.scene.entities[i];
5235                         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));
5236                 }
5237         }
5238         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5239                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5240         {
5241                 for (i = 0;i < r_refdef.scene.numentities;i++)
5242                 {
5243                         if (!r_refdef.viewcache.entityvisible[i])
5244                                 continue;
5245                         ent = r_refdef.scene.entities[i];
5246                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5247                         {
5248                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5249                                 if (samples < 0)
5250                                         continue; // temp entities do pvs only
5251                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5252                                         ent->last_trace_visibility = realtime;
5253                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5254                                         r_refdef.viewcache.entityvisible[i] = 0;
5255                         }
5256                 }
5257         }
5258 }
5259
5260 /// only used if skyrendermasked, and normally returns false
5261 static int R_DrawBrushModelsSky (void)
5262 {
5263         int i, sky;
5264         entity_render_t *ent;
5265
5266         sky = false;
5267         for (i = 0;i < r_refdef.scene.numentities;i++)
5268         {
5269                 if (!r_refdef.viewcache.entityvisible[i])
5270                         continue;
5271                 ent = r_refdef.scene.entities[i];
5272                 if (!ent->model || !ent->model->DrawSky)
5273                         continue;
5274                 ent->model->DrawSky(ent);
5275                 sky = true;
5276         }
5277         return sky;
5278 }
5279
5280 static void R_DrawNoModel(entity_render_t *ent);
5281 static void R_DrawModels(void)
5282 {
5283         int i;
5284         entity_render_t *ent;
5285
5286         for (i = 0;i < r_refdef.scene.numentities;i++)
5287         {
5288                 if (!r_refdef.viewcache.entityvisible[i])
5289                         continue;
5290                 ent = r_refdef.scene.entities[i];
5291                 r_refdef.stats[r_stat_entities]++;
5292                 /*
5293                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5294                 {
5295                         vec3_t f, l, u, o;
5296                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5297                         Con_Printf("R_DrawModels\n");
5298                         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]);
5299                         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);
5300                         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);
5301                 }
5302                 */
5303                 if (ent->model && ent->model->Draw != NULL)
5304                         ent->model->Draw(ent);
5305                 else
5306                         R_DrawNoModel(ent);
5307         }
5308 }
5309
5310 static void R_DrawModelsDepth(void)
5311 {
5312         int i;
5313         entity_render_t *ent;
5314
5315         for (i = 0;i < r_refdef.scene.numentities;i++)
5316         {
5317                 if (!r_refdef.viewcache.entityvisible[i])
5318                         continue;
5319                 ent = r_refdef.scene.entities[i];
5320                 if (ent->model && ent->model->DrawDepth != NULL)
5321                         ent->model->DrawDepth(ent);
5322         }
5323 }
5324
5325 static void R_DrawModelsDebug(void)
5326 {
5327         int i;
5328         entity_render_t *ent;
5329
5330         for (i = 0;i < r_refdef.scene.numentities;i++)
5331         {
5332                 if (!r_refdef.viewcache.entityvisible[i])
5333                         continue;
5334                 ent = r_refdef.scene.entities[i];
5335                 if (ent->model && ent->model->DrawDebug != NULL)
5336                         ent->model->DrawDebug(ent);
5337         }
5338 }
5339
5340 static void R_DrawModelsAddWaterPlanes(void)
5341 {
5342         int i;
5343         entity_render_t *ent;
5344
5345         for (i = 0;i < r_refdef.scene.numentities;i++)
5346         {
5347                 if (!r_refdef.viewcache.entityvisible[i])
5348                         continue;
5349                 ent = r_refdef.scene.entities[i];
5350                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5351                         ent->model->DrawAddWaterPlanes(ent);
5352         }
5353 }
5354
5355 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}};
5356
5357 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5358 {
5359         if (r_hdr_irisadaptation.integer)
5360         {
5361                 vec3_t p;
5362                 vec3_t ambient;
5363                 vec3_t diffuse;
5364                 vec3_t diffusenormal;
5365                 vec3_t forward;
5366                 vec_t brightness = 0.0f;
5367                 vec_t goal;
5368                 vec_t current;
5369                 vec_t d;
5370                 int c;
5371                 VectorCopy(r_refdef.view.forward, forward);
5372                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5373                 {
5374                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5375                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5376                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5377                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5378                         d = DotProduct(forward, diffusenormal);
5379                         brightness += VectorLength(ambient);
5380                         if (d > 0)
5381                                 brightness += d * VectorLength(diffuse);
5382                 }
5383                 brightness *= 1.0f / c;
5384                 brightness += 0.00001f; // make sure it's never zero
5385                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5386                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5387                 current = r_hdr_irisadaptation_value.value;
5388                 if (current < goal)
5389                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5390                 else if (current > goal)
5391                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5392                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5393                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5394         }
5395         else if (r_hdr_irisadaptation_value.value != 1.0f)
5396                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5397 }
5398
5399 static void R_View_SetFrustum(const int *scissor)
5400 {
5401         int i;
5402         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5403         vec3_t forward, left, up, origin, v;
5404
5405         if(scissor)
5406         {
5407                 // flipped x coordinates (because x points left here)
5408                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5409                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5410
5411                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5412                 switch(vid.renderpath)
5413                 {
5414                         case RENDERPATH_D3D9:
5415                         case RENDERPATH_D3D10:
5416                         case RENDERPATH_D3D11:
5417                                 // non-flipped y coordinates
5418                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5419                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5420                                 break;
5421                         case RENDERPATH_SOFT:
5422                         case RENDERPATH_GL11:
5423                         case RENDERPATH_GL13:
5424                         case RENDERPATH_GL20:
5425                         case RENDERPATH_GLES1:
5426                         case RENDERPATH_GLES2:
5427                                 // non-flipped y coordinates
5428                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5429                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5430                                 break;
5431                 }
5432         }
5433
5434         // we can't trust r_refdef.view.forward and friends in reflected scenes
5435         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5436
5437 #if 0
5438         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5439         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5440         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5441         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5442         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5443         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5444         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5445         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5446         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5447         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5448         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5449         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5450 #endif
5451
5452 #if 0
5453         zNear = r_refdef.nearclip;
5454         nudge = 1.0 - 1.0 / (1<<23);
5455         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5456         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5457         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5458         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5459         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5460         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5461         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5462         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5463 #endif
5464
5465
5466
5467 #if 0
5468         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5469         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5470         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5471         r_refdef.view.frustum[0].dist = m[15] - m[12];
5472
5473         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5474         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5475         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5476         r_refdef.view.frustum[1].dist = m[15] + m[12];
5477
5478         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5479         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5480         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5481         r_refdef.view.frustum[2].dist = m[15] - m[13];
5482
5483         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5484         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5485         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5486         r_refdef.view.frustum[3].dist = m[15] + m[13];
5487
5488         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5489         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5490         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5491         r_refdef.view.frustum[4].dist = m[15] - m[14];
5492
5493         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5494         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5495         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5496         r_refdef.view.frustum[5].dist = m[15] + m[14];
5497 #endif
5498
5499         if (r_refdef.view.useperspective)
5500         {
5501                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5502                 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]);
5503                 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]);
5504                 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]);
5505                 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]);
5506
5507                 // then the normals from the corners relative to origin
5508                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5509                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5510                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5511                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5512
5513                 // in a NORMAL view, forward cross left == up
5514                 // in a REFLECTED view, forward cross left == down
5515                 // so our cross products above need to be adjusted for a left handed coordinate system
5516                 CrossProduct(forward, left, v);
5517                 if(DotProduct(v, up) < 0)
5518                 {
5519                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5520                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5521                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5522                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5523                 }
5524
5525                 // Leaving those out was a mistake, those were in the old code, and they
5526                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5527                 // I couldn't reproduce it after adding those normalizations. --blub
5528                 VectorNormalize(r_refdef.view.frustum[0].normal);
5529                 VectorNormalize(r_refdef.view.frustum[1].normal);
5530                 VectorNormalize(r_refdef.view.frustum[2].normal);
5531                 VectorNormalize(r_refdef.view.frustum[3].normal);
5532
5533                 // make the corners absolute
5534                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5535                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5536                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5537                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5538
5539                 // one more normal
5540                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5541
5542                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5543                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5544                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5545                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5546                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5547         }
5548         else
5549         {
5550                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5551                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5552                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5553                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5554                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5555                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5556                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5557                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5558                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5559                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5560         }
5561         r_refdef.view.numfrustumplanes = 5;
5562
5563         if (r_refdef.view.useclipplane)
5564         {
5565                 r_refdef.view.numfrustumplanes = 6;
5566                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5567         }
5568
5569         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5570                 PlaneClassify(r_refdef.view.frustum + i);
5571
5572         // LordHavoc: note to all quake engine coders, Quake had a special case
5573         // for 90 degrees which assumed a square view (wrong), so I removed it,
5574         // Quake2 has it disabled as well.
5575
5576         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5577         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5578         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5579         //PlaneClassify(&frustum[0]);
5580
5581         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5582         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5583         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5584         //PlaneClassify(&frustum[1]);
5585
5586         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5587         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5588         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5589         //PlaneClassify(&frustum[2]);
5590
5591         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5592         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5593         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5594         //PlaneClassify(&frustum[3]);
5595
5596         // nearclip plane
5597         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5598         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5599         //PlaneClassify(&frustum[4]);
5600 }
5601
5602 static void R_View_UpdateWithScissor(const int *myscissor)
5603 {
5604         R_Main_ResizeViewCache();
5605         R_View_SetFrustum(myscissor);
5606         R_View_WorldVisibility(r_refdef.view.useclipplane);
5607         R_View_UpdateEntityVisible();
5608         R_View_UpdateEntityLighting();
5609 }
5610
5611 static void R_View_Update(void)
5612 {
5613         R_Main_ResizeViewCache();
5614         R_View_SetFrustum(NULL);
5615         R_View_WorldVisibility(r_refdef.view.useclipplane);
5616         R_View_UpdateEntityVisible();
5617         R_View_UpdateEntityLighting();
5618 }
5619
5620 float viewscalefpsadjusted = 1.0f;
5621
5622 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5623 {
5624         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5625         scale = bound(0.03125f, scale, 1.0f);
5626         *outwidth = (int)ceil(width * scale);
5627         *outheight = (int)ceil(height * scale);
5628 }
5629
5630 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5631 {
5632         const float *customclipplane = NULL;
5633         float plane[4];
5634         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5635         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5636         {
5637                 // LordHavoc: couldn't figure out how to make this approach the
5638                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5639                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5640                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5641                         dist = r_refdef.view.clipplane.dist;
5642                 plane[0] = r_refdef.view.clipplane.normal[0];
5643                 plane[1] = r_refdef.view.clipplane.normal[1];
5644                 plane[2] = r_refdef.view.clipplane.normal[2];
5645                 plane[3] = -dist;
5646                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5647         }
5648
5649         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5650         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5651
5652         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5653         if (!r_refdef.view.useperspective)
5654                 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);
5655         else if (vid.stencil && r_useinfinitefarclip.integer)
5656                 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);
5657         else
5658                 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);
5659         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5660         R_SetViewport(&r_refdef.view.viewport);
5661         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5662         {
5663                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5664                 float screenplane[4];
5665                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5666                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5667                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5668                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5669                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5670         }
5671 }
5672
5673 void R_EntityMatrix(const matrix4x4_t *matrix)
5674 {
5675         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5676         {
5677                 gl_modelmatrixchanged = false;
5678                 gl_modelmatrix = *matrix;
5679                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5680                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5681                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5682                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5683                 CHECKGLERROR
5684                 switch(vid.renderpath)
5685                 {
5686                 case RENDERPATH_D3D9:
5687 #ifdef SUPPORTD3D
5688                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5689                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5690 #endif
5691                         break;
5692                 case RENDERPATH_D3D10:
5693                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5694                         break;
5695                 case RENDERPATH_D3D11:
5696                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5697                         break;
5698                 case RENDERPATH_GL11:
5699                 case RENDERPATH_GL13:
5700                 case RENDERPATH_GLES1:
5701 #ifndef USE_GLES2
5702                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5703 #endif
5704                         break;
5705                 case RENDERPATH_SOFT:
5706                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5707                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5708                         break;
5709                 case RENDERPATH_GL20:
5710                 case RENDERPATH_GLES2:
5711                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5712                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5713                         break;
5714                 }
5715         }
5716 }
5717
5718 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5719 {
5720         r_viewport_t viewport;
5721
5722         CHECKGLERROR
5723
5724         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5725         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);
5726         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5727         R_SetViewport(&viewport);
5728         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5729         GL_Color(1, 1, 1, 1);
5730         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5731         GL_BlendFunc(GL_ONE, GL_ZERO);
5732         GL_ScissorTest(false);
5733         GL_DepthMask(false);
5734         GL_DepthRange(0, 1);
5735         GL_DepthTest(false);
5736         GL_DepthFunc(GL_LEQUAL);
5737         R_EntityMatrix(&identitymatrix);
5738         R_Mesh_ResetTextureState();
5739         GL_PolygonOffset(0, 0);
5740         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5741         switch(vid.renderpath)
5742         {
5743         case RENDERPATH_GL11:
5744         case RENDERPATH_GL13:
5745         case RENDERPATH_GL20:
5746         case RENDERPATH_GLES1:
5747         case RENDERPATH_GLES2:
5748                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5749                 break;
5750         case RENDERPATH_D3D9:
5751         case RENDERPATH_D3D10:
5752         case RENDERPATH_D3D11:
5753         case RENDERPATH_SOFT:
5754                 break;
5755         }
5756         GL_CullFace(GL_NONE);
5757
5758         CHECKGLERROR
5759 }
5760
5761 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5762 {
5763         DrawQ_Finish();
5764
5765         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5766 }
5767
5768 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5769 {
5770         DrawQ_Finish();
5771
5772         R_SetupView(true, fbo, depthtexture, colortexture);
5773         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5774         GL_Color(1, 1, 1, 1);
5775         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5776         GL_BlendFunc(GL_ONE, GL_ZERO);
5777         GL_ScissorTest(true);
5778         GL_DepthMask(true);
5779         GL_DepthRange(0, 1);
5780         GL_DepthTest(true);
5781         GL_DepthFunc(GL_LEQUAL);
5782         R_EntityMatrix(&identitymatrix);
5783         R_Mesh_ResetTextureState();
5784         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5785         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5786         switch(vid.renderpath)
5787         {
5788         case RENDERPATH_GL11:
5789         case RENDERPATH_GL13:
5790         case RENDERPATH_GL20:
5791         case RENDERPATH_GLES1:
5792         case RENDERPATH_GLES2:
5793                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5794                 break;
5795         case RENDERPATH_D3D9:
5796         case RENDERPATH_D3D10:
5797         case RENDERPATH_D3D11:
5798         case RENDERPATH_SOFT:
5799                 break;
5800         }
5801         GL_CullFace(r_refdef.view.cullface_back);
5802 }
5803
5804 /*
5805 ================
5806 R_RenderView_UpdateViewVectors
5807 ================
5808 */
5809 void R_RenderView_UpdateViewVectors(void)
5810 {
5811         // break apart the view matrix into vectors for various purposes
5812         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5813         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5814         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5815         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5816         // make an inverted copy of the view matrix for tracking sprites
5817         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5818 }
5819
5820 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5821 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5822
5823 static void R_Water_StartFrame(void)
5824 {
5825         int i;
5826         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5827         r_waterstate_waterplane_t *p;
5828         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;
5829
5830         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5831                 return;
5832
5833         switch(vid.renderpath)
5834         {
5835         case RENDERPATH_GL20:
5836         case RENDERPATH_D3D9:
5837         case RENDERPATH_D3D10:
5838         case RENDERPATH_D3D11:
5839         case RENDERPATH_SOFT:
5840         case RENDERPATH_GLES2:
5841                 break;
5842         case RENDERPATH_GL11:
5843         case RENDERPATH_GL13:
5844         case RENDERPATH_GLES1:
5845                 return;
5846         }
5847
5848         // set waterwidth and waterheight to the water resolution that will be
5849         // used (often less than the screen resolution for faster rendering)
5850         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5851
5852         // calculate desired texture sizes
5853         // can't use water if the card does not support the texture size
5854         if (!r_water.integer || r_showsurfaces.integer)
5855                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5856         else if (vid.support.arb_texture_non_power_of_two)
5857         {
5858                 texturewidth = waterwidth;
5859                 textureheight = waterheight;
5860                 camerawidth = waterwidth;
5861                 cameraheight = waterheight;
5862         }
5863         else
5864         {
5865                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5866                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5867                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5868                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5869         }
5870
5871         // allocate textures as needed
5872         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))
5873         {
5874                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5875                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5876                 {
5877                         if (p->texture_refraction)
5878                                 R_FreeTexture(p->texture_refraction);
5879                         p->texture_refraction = NULL;
5880                         if (p->fbo_refraction)
5881                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5882                         p->fbo_refraction = 0;
5883                         if (p->texture_reflection)
5884                                 R_FreeTexture(p->texture_reflection);
5885                         p->texture_reflection = NULL;
5886                         if (p->fbo_reflection)
5887                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5888                         p->fbo_reflection = 0;
5889                         if (p->texture_camera)
5890                                 R_FreeTexture(p->texture_camera);
5891                         p->texture_camera = NULL;
5892                         if (p->fbo_camera)
5893                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5894                         p->fbo_camera = 0;
5895                 }
5896                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5897                 r_fb.water.texturewidth = texturewidth;
5898                 r_fb.water.textureheight = textureheight;
5899                 r_fb.water.camerawidth = camerawidth;
5900                 r_fb.water.cameraheight = cameraheight;
5901         }
5902
5903         if (r_fb.water.texturewidth)
5904         {
5905                 int scaledwidth, scaledheight;
5906
5907                 r_fb.water.enabled = true;
5908
5909                 // water resolution is usually reduced
5910                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5911                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5912                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5913
5914                 // set up variables that will be used in shader setup
5915                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5916                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5917                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5918                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5919         }
5920
5921         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5922         r_fb.water.numwaterplanes = 0;
5923 }
5924
5925 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5926 {
5927         int planeindex, bestplaneindex, vertexindex;
5928         vec3_t mins, maxs, normal, center, v, n;
5929         vec_t planescore, bestplanescore;
5930         mplane_t plane;
5931         r_waterstate_waterplane_t *p;
5932         texture_t *t = R_GetCurrentTexture(surface->texture);
5933
5934         rsurface.texture = t;
5935         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5936         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5937         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5938                 return;
5939         // average the vertex normals, find the surface bounds (after deformvertexes)
5940         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5941         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5942         VectorCopy(n, normal);
5943         VectorCopy(v, mins);
5944         VectorCopy(v, maxs);
5945         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5946         {
5947                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5948                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5949                 VectorAdd(normal, n, normal);
5950                 mins[0] = min(mins[0], v[0]);
5951                 mins[1] = min(mins[1], v[1]);
5952                 mins[2] = min(mins[2], v[2]);
5953                 maxs[0] = max(maxs[0], v[0]);
5954                 maxs[1] = max(maxs[1], v[1]);
5955                 maxs[2] = max(maxs[2], v[2]);
5956         }
5957         VectorNormalize(normal);
5958         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5959
5960         VectorCopy(normal, plane.normal);
5961         VectorNormalize(plane.normal);
5962         plane.dist = DotProduct(center, plane.normal);
5963         PlaneClassify(&plane);
5964         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5965         {
5966                 // skip backfaces (except if nocullface is set)
5967 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5968 //                      return;
5969                 VectorNegate(plane.normal, plane.normal);
5970                 plane.dist *= -1;
5971                 PlaneClassify(&plane);
5972         }
5973
5974
5975         // find a matching plane if there is one
5976         bestplaneindex = -1;
5977         bestplanescore = 1048576.0f;
5978         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5979         {
5980                 if(p->camera_entity == t->camera_entity)
5981                 {
5982                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5983                         if (bestplaneindex < 0 || bestplanescore > planescore)
5984                         {
5985                                 bestplaneindex = planeindex;
5986                                 bestplanescore = planescore;
5987                         }
5988                 }
5989         }
5990         planeindex = bestplaneindex;
5991         p = r_fb.water.waterplanes + planeindex;
5992
5993         // if this surface does not fit any known plane rendered this frame, add one
5994         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5995         {
5996                 // store the new plane
5997                 planeindex = r_fb.water.numwaterplanes++;
5998                 p = r_fb.water.waterplanes + planeindex;
5999                 p->plane = plane;
6000                 // clear materialflags and pvs
6001                 p->materialflags = 0;
6002                 p->pvsvalid = false;
6003                 p->camera_entity = t->camera_entity;
6004                 VectorCopy(mins, p->mins);
6005                 VectorCopy(maxs, p->maxs);
6006         }
6007         else
6008         {
6009                 // merge mins/maxs when we're adding this surface to the plane
6010                 p->mins[0] = min(p->mins[0], mins[0]);
6011                 p->mins[1] = min(p->mins[1], mins[1]);
6012                 p->mins[2] = min(p->mins[2], mins[2]);
6013                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6014                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6015                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6016         }
6017         // merge this surface's materialflags into the waterplane
6018         p->materialflags |= t->currentmaterialflags;
6019         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6020         {
6021                 // merge this surface's PVS into the waterplane
6022                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6023                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6024                 {
6025                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6026                         p->pvsvalid = true;
6027                 }
6028         }
6029 }
6030
6031 extern cvar_t r_drawparticles;
6032 extern cvar_t r_drawdecals;
6033
6034 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6035 {
6036         int myscissor[4];
6037         r_refdef_view_t originalview;
6038         r_refdef_view_t myview;
6039         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;
6040         r_waterstate_waterplane_t *p;
6041         vec3_t visorigin;
6042         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;
6043         char vabuf[1024];
6044
6045         originalview = r_refdef.view;
6046
6047         // lowquality hack, temporarily shut down some cvars and restore afterwards
6048         qualityreduction = r_water_lowquality.integer;
6049         if (qualityreduction > 0)
6050         {
6051                 if (qualityreduction >= 1)
6052                 {
6053                         old_r_shadows = r_shadows.integer;
6054                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6055                         old_r_dlight = r_shadow_realtime_dlight.integer;
6056                         Cvar_SetValueQuick(&r_shadows, 0);
6057                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6058                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6059                 }
6060                 if (qualityreduction >= 2)
6061                 {
6062                         old_r_dynamic = r_dynamic.integer;
6063                         old_r_particles = r_drawparticles.integer;
6064                         old_r_decals = r_drawdecals.integer;
6065                         Cvar_SetValueQuick(&r_dynamic, 0);
6066                         Cvar_SetValueQuick(&r_drawparticles, 0);
6067                         Cvar_SetValueQuick(&r_drawdecals, 0);
6068                 }
6069         }
6070
6071         // make sure enough textures are allocated
6072         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6073         {
6074                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6075                 {
6076                         if (!p->texture_refraction)
6077                                 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);
6078                         if (!p->texture_refraction)
6079                                 goto error;
6080                         if (usewaterfbo)
6081                         {
6082                                 if (r_fb.water.depthtexture == NULL)
6083                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6084                                 if (p->fbo_refraction == 0)
6085                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6086                         }
6087                 }
6088                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6089                 {
6090                         if (!p->texture_camera)
6091                                 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);
6092                         if (!p->texture_camera)
6093                                 goto error;
6094                         if (usewaterfbo)
6095                         {
6096                                 if (r_fb.water.depthtexture == NULL)
6097                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6098                                 if (p->fbo_camera == 0)
6099                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6100                         }
6101                 }
6102
6103                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6104                 {
6105                         if (!p->texture_reflection)
6106                                 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);
6107                         if (!p->texture_reflection)
6108                                 goto error;
6109                         if (usewaterfbo)
6110                         {
6111                                 if (r_fb.water.depthtexture == NULL)
6112                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6113                                 if (p->fbo_reflection == 0)
6114                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6115                         }
6116                 }
6117         }
6118
6119         // render views
6120         r_refdef.view = originalview;
6121         r_refdef.view.showdebug = false;
6122         r_refdef.view.width = r_fb.water.waterwidth;
6123         r_refdef.view.height = r_fb.water.waterheight;
6124         r_refdef.view.useclipplane = true;
6125         myview = r_refdef.view;
6126         r_fb.water.renderingscene = true;
6127         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6128         {
6129                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6130                 {
6131                         r_refdef.view = myview;
6132                         if(r_water_scissormode.integer)
6133                         {
6134                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6135                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6136                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6137                         }
6138
6139                         // render reflected scene and copy into texture
6140                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6141                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6142                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6143                         r_refdef.view.clipplane = p->plane;
6144                         // reverse the cullface settings for this render
6145                         r_refdef.view.cullface_front = GL_FRONT;
6146                         r_refdef.view.cullface_back = GL_BACK;
6147                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6148                         {
6149                                 r_refdef.view.usecustompvs = true;
6150                                 if (p->pvsvalid)
6151                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6152                                 else
6153                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6154                         }
6155
6156                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6157                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6158                         R_ClearScreen(r_refdef.fogenabled);
6159                         if(r_water_scissormode.integer & 2)
6160                                 R_View_UpdateWithScissor(myscissor);
6161                         else
6162                                 R_View_Update();
6163                         R_AnimCache_CacheVisibleEntities();
6164                         if(r_water_scissormode.integer & 1)
6165                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6166                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6167
6168                         if (!p->fbo_reflection)
6169                                 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);
6170                         r_fb.water.hideplayer = false;
6171                 }
6172
6173                 // render the normal view scene and copy into texture
6174                 // (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)
6175                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6176                 {
6177                         r_refdef.view = myview;
6178                         if(r_water_scissormode.integer)
6179                         {
6180                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6181                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6182                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6183                         }
6184
6185                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6186
6187                         r_refdef.view.clipplane = p->plane;
6188                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6189                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6190
6191                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6192                         {
6193                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6194                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6195                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6196                                 R_RenderView_UpdateViewVectors();
6197                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6198                                 {
6199                                         r_refdef.view.usecustompvs = true;
6200                                         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);
6201                                 }
6202                         }
6203
6204                         PlaneClassify(&r_refdef.view.clipplane);
6205
6206                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6207                         R_ClearScreen(r_refdef.fogenabled);
6208                         if(r_water_scissormode.integer & 2)
6209                                 R_View_UpdateWithScissor(myscissor);
6210                         else
6211                                 R_View_Update();
6212                         R_AnimCache_CacheVisibleEntities();
6213                         if(r_water_scissormode.integer & 1)
6214                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6215                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6216
6217                         if (!p->fbo_refraction)
6218                                 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);
6219                         r_fb.water.hideplayer = false;
6220                 }
6221                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6222                 {
6223                         r_refdef.view = myview;
6224
6225                         r_refdef.view.clipplane = p->plane;
6226                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6227                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6228
6229                         r_refdef.view.width = r_fb.water.camerawidth;
6230                         r_refdef.view.height = r_fb.water.cameraheight;
6231                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6232                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6233                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6234                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6235
6236                         if(p->camera_entity)
6237                         {
6238                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6239                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6240                         }
6241
6242                         // note: all of the view is used for displaying... so
6243                         // there is no use in scissoring
6244
6245                         // reverse the cullface settings for this render
6246                         r_refdef.view.cullface_front = GL_FRONT;
6247                         r_refdef.view.cullface_back = GL_BACK;
6248                         // also reverse the view matrix
6249                         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
6250                         R_RenderView_UpdateViewVectors();
6251                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6252                         {
6253                                 r_refdef.view.usecustompvs = true;
6254                                 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);
6255                         }
6256                         
6257                         // camera needs no clipplane
6258                         r_refdef.view.useclipplane = false;
6259
6260                         PlaneClassify(&r_refdef.view.clipplane);
6261
6262                         r_fb.water.hideplayer = false;
6263
6264                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6265                         R_ClearScreen(r_refdef.fogenabled);
6266                         R_View_Update();
6267                         R_AnimCache_CacheVisibleEntities();
6268                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6269
6270                         if (!p->fbo_camera)
6271                                 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);
6272                         r_fb.water.hideplayer = false;
6273                 }
6274
6275         }
6276         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6277         r_fb.water.renderingscene = false;
6278         r_refdef.view = originalview;
6279         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6280         if (!r_fb.water.depthtexture)
6281                 R_ClearScreen(r_refdef.fogenabled);
6282         R_View_Update();
6283         R_AnimCache_CacheVisibleEntities();
6284         goto finish;
6285 error:
6286         r_refdef.view = originalview;
6287         r_fb.water.renderingscene = false;
6288         Cvar_SetValueQuick(&r_water, 0);
6289         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6290 finish:
6291         // lowquality hack, restore cvars
6292         if (qualityreduction > 0)
6293         {
6294                 if (qualityreduction >= 1)
6295                 {
6296                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6297                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6298                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6299                 }
6300                 if (qualityreduction >= 2)
6301                 {
6302                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6303                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6304                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6305                 }
6306         }
6307 }
6308
6309 static void R_Bloom_StartFrame(void)
6310 {
6311         int i;
6312         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6313         int viewwidth, viewheight;
6314         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6315         textype_t textype = TEXTYPE_COLORBUFFER;
6316
6317         switch (vid.renderpath)
6318         {
6319         case RENDERPATH_GL20:
6320                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6321                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6322                 {
6323                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6324                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6325                 }
6326                 break;
6327         case RENDERPATH_GL11:
6328         case RENDERPATH_GL13:
6329         case RENDERPATH_GLES1:
6330         case RENDERPATH_GLES2:
6331         case RENDERPATH_D3D9:
6332         case RENDERPATH_D3D10:
6333         case RENDERPATH_D3D11:
6334                 r_fb.usedepthtextures = false;
6335                 break;
6336         case RENDERPATH_SOFT:
6337                 r_fb.usedepthtextures = true;
6338                 break;
6339         }
6340
6341         if (r_viewscale_fpsscaling.integer)
6342         {
6343                 double actualframetime;
6344                 double targetframetime;
6345                 double adjust;
6346                 actualframetime = r_refdef.lastdrawscreentime;
6347                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6348                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6349                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6350                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6351                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6352                 viewscalefpsadjusted += adjust;
6353                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6354         }
6355         else
6356                 viewscalefpsadjusted = 1.0f;
6357
6358         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6359
6360         switch(vid.renderpath)
6361         {
6362         case RENDERPATH_GL20:
6363         case RENDERPATH_D3D9:
6364         case RENDERPATH_D3D10:
6365         case RENDERPATH_D3D11:
6366         case RENDERPATH_SOFT:
6367         case RENDERPATH_GLES2:
6368                 break;
6369         case RENDERPATH_GL11:
6370         case RENDERPATH_GL13:
6371         case RENDERPATH_GLES1:
6372                 return;
6373         }
6374
6375         // set bloomwidth and bloomheight to the bloom resolution that will be
6376         // used (often less than the screen resolution for faster rendering)
6377         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6378         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6379         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6380         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6381         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6382
6383         // calculate desired texture sizes
6384         if (vid.support.arb_texture_non_power_of_two)
6385         {
6386                 screentexturewidth = vid.width;
6387                 screentextureheight = vid.height;
6388                 bloomtexturewidth = r_fb.bloomwidth;
6389                 bloomtextureheight = r_fb.bloomheight;
6390         }
6391         else
6392         {
6393                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6394                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6395                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6396                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6397         }
6398
6399         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))
6400         {
6401                 Cvar_SetValueQuick(&r_bloom, 0);
6402                 Cvar_SetValueQuick(&r_motionblur, 0);
6403                 Cvar_SetValueQuick(&r_damageblur, 0);
6404         }
6405
6406         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6407          && !r_bloom.integer
6408          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6409          && !useviewfbo
6410          && r_viewscale.value == 1.0f
6411          && !r_viewscale_fpsscaling.integer)
6412                 screentexturewidth = screentextureheight = 0;
6413         if (!r_bloom.integer)
6414                 bloomtexturewidth = bloomtextureheight = 0;
6415
6416         // allocate textures as needed
6417         if (r_fb.screentexturewidth != screentexturewidth
6418          || r_fb.screentextureheight != screentextureheight
6419          || r_fb.bloomtexturewidth != bloomtexturewidth
6420          || r_fb.bloomtextureheight != bloomtextureheight
6421          || r_fb.textype != textype
6422          || useviewfbo != (r_fb.fbo != 0))
6423         {
6424                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6425                 {
6426                         if (r_fb.bloomtexture[i])
6427                                 R_FreeTexture(r_fb.bloomtexture[i]);
6428                         r_fb.bloomtexture[i] = NULL;
6429
6430                         if (r_fb.bloomfbo[i])
6431                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6432                         r_fb.bloomfbo[i] = 0;
6433                 }
6434
6435                 if (r_fb.fbo)
6436                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6437                 r_fb.fbo = 0;
6438
6439                 if (r_fb.colortexture)
6440                         R_FreeTexture(r_fb.colortexture);
6441                 r_fb.colortexture = NULL;
6442
6443                 if (r_fb.depthtexture)
6444                         R_FreeTexture(r_fb.depthtexture);
6445                 r_fb.depthtexture = NULL;
6446
6447                 if (r_fb.ghosttexture)
6448                         R_FreeTexture(r_fb.ghosttexture);
6449                 r_fb.ghosttexture = NULL;
6450
6451                 r_fb.screentexturewidth = screentexturewidth;
6452                 r_fb.screentextureheight = screentextureheight;
6453                 r_fb.bloomtexturewidth = bloomtexturewidth;
6454                 r_fb.bloomtextureheight = bloomtextureheight;
6455                 r_fb.textype = textype;
6456
6457                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6458                 {
6459                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6460                                 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);
6461                         r_fb.ghosttexture_valid = false;
6462                         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);
6463                         if (useviewfbo)
6464                         {
6465                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6466                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6467                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6468                         }
6469                 }
6470
6471                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6472                 {
6473                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6474                         {
6475                                 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);
6476                                 if (useviewfbo)
6477                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6478                         }
6479                 }
6480         }
6481
6482         // bloom texture is a different resolution
6483         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6484         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6485         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6486         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6487         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6488
6489         // set up a texcoord array for the full resolution screen image
6490         // (we have to keep this around to copy back during final render)
6491         r_fb.screentexcoord2f[0] = 0;
6492         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6493         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6494         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6495         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6496         r_fb.screentexcoord2f[5] = 0;
6497         r_fb.screentexcoord2f[6] = 0;
6498         r_fb.screentexcoord2f[7] = 0;
6499
6500         if(r_fb.fbo) 
6501         {
6502                 for (i = 1;i < 8;i += 2)
6503                 {
6504                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6505                 }
6506         }
6507
6508         // set up a texcoord array for the reduced resolution bloom image
6509         // (which will be additive blended over the screen image)
6510         r_fb.bloomtexcoord2f[0] = 0;
6511         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6512         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6513         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6514         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6515         r_fb.bloomtexcoord2f[5] = 0;
6516         r_fb.bloomtexcoord2f[6] = 0;
6517         r_fb.bloomtexcoord2f[7] = 0;
6518
6519         switch(vid.renderpath)
6520         {
6521         case RENDERPATH_GL11:
6522         case RENDERPATH_GL13:
6523         case RENDERPATH_GL20:
6524         case RENDERPATH_SOFT:
6525         case RENDERPATH_GLES1:
6526         case RENDERPATH_GLES2:
6527                 break;
6528         case RENDERPATH_D3D9:
6529         case RENDERPATH_D3D10:
6530         case RENDERPATH_D3D11:
6531                 for (i = 0;i < 4;i++)
6532                 {
6533                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6534                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6535                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6536                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6537                 }
6538                 break;
6539         }
6540
6541         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6542
6543         if (r_fb.fbo)
6544                 r_refdef.view.clear = true;
6545 }
6546
6547 static void R_Bloom_MakeTexture(void)
6548 {
6549         int x, range, dir;
6550         float xoffset, yoffset, r, brighten;
6551         rtexture_t *intex;
6552         float colorscale = r_bloom_colorscale.value;
6553
6554         r_refdef.stats[r_stat_bloom]++;
6555     
6556 #if 0
6557     // this copy is unnecessary since it happens in R_BlendView already
6558         if (!r_fb.fbo)
6559         {
6560                 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);
6561                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6562         }
6563 #endif
6564
6565         // scale down screen texture to the bloom texture size
6566         CHECKGLERROR
6567         r_fb.bloomindex = 0;
6568         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6569         R_SetViewport(&r_fb.bloomviewport);
6570         GL_DepthTest(false);
6571         GL_BlendFunc(GL_ONE, GL_ZERO);
6572         GL_Color(colorscale, colorscale, colorscale, 1);
6573         // 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...
6574         switch(vid.renderpath)
6575         {
6576         case RENDERPATH_GL11:
6577         case RENDERPATH_GL13:
6578         case RENDERPATH_GL20:
6579         case RENDERPATH_GLES1:
6580         case RENDERPATH_GLES2:
6581         case RENDERPATH_SOFT:
6582                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6583                 break;
6584         case RENDERPATH_D3D9:
6585         case RENDERPATH_D3D10:
6586         case RENDERPATH_D3D11:
6587                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6588                 break;
6589         }
6590         // TODO: do boxfilter scale-down in shader?
6591         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6592         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6593         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6594
6595         // we now have a properly scaled bloom image
6596         if (!r_fb.bloomfbo[r_fb.bloomindex])
6597         {
6598                 // copy it into the bloom texture
6599                 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);
6600                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6601         }
6602
6603         // multiply bloom image by itself as many times as desired
6604         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6605         {
6606                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6607                 r_fb.bloomindex ^= 1;
6608                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6609                 x *= 2;
6610                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6611                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6612                 {
6613                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6614                         GL_Color(r,r,r,1); // apply fix factor
6615                 }
6616                 else
6617                 {
6618                         if(x <= 2)
6619                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6620                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6621                         GL_Color(1,1,1,1); // no fix factor supported here
6622                 }
6623                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6624                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6625                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6626                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6627
6628                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6629                 {
6630                         // copy the darkened image to a texture
6631                         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);
6632                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6633                 }
6634         }
6635
6636         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6637         brighten = r_bloom_brighten.value;
6638         brighten = sqrt(brighten);
6639         if(range >= 1)
6640                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6641
6642         for (dir = 0;dir < 2;dir++)
6643         {
6644                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6645                 r_fb.bloomindex ^= 1;
6646                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6647                 // blend on at multiple vertical offsets to achieve a vertical blur
6648                 // TODO: do offset blends using GLSL
6649                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6650                 GL_BlendFunc(GL_ONE, GL_ZERO);
6651                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6652                 for (x = -range;x <= range;x++)
6653                 {
6654                         if (!dir){xoffset = 0;yoffset = x;}
6655                         else {xoffset = x;yoffset = 0;}
6656                         xoffset /= (float)r_fb.bloomtexturewidth;
6657                         yoffset /= (float)r_fb.bloomtextureheight;
6658                         // compute a texcoord array with the specified x and y offset
6659                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6660                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6661                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6662                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6663                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6664                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6665                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6666                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6667                         // this r value looks like a 'dot' particle, fading sharply to
6668                         // black at the edges
6669                         // (probably not realistic but looks good enough)
6670                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6671                         //r = brighten/(range*2+1);
6672                         r = brighten / (range * 2 + 1);
6673                         if(range >= 1)
6674                                 r *= (1 - x*x/(float)(range*range));
6675                         GL_Color(r, r, r, 1);
6676                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6677                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6678                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6679                         GL_BlendFunc(GL_ONE, GL_ONE);
6680                 }
6681
6682                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6683                 {
6684                         // copy the vertically or horizontally blurred bloom view to a texture
6685                         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);
6686                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6687                 }
6688         }
6689 }
6690
6691 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6692 {
6693         unsigned int permutation;
6694         float uservecs[4][4];
6695
6696         R_EntityMatrix(&identitymatrix);
6697
6698         switch (vid.renderpath)
6699         {
6700         case RENDERPATH_GL20:
6701         case RENDERPATH_D3D9:
6702         case RENDERPATH_D3D10:
6703         case RENDERPATH_D3D11:
6704         case RENDERPATH_SOFT:
6705         case RENDERPATH_GLES2:
6706                 permutation =
6707                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6708                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6709                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6710                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6711                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6712
6713                 if (r_fb.colortexture)
6714                 {
6715                         if (!r_fb.fbo)
6716                         {
6717                                 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);
6718                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6719                         }
6720
6721                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6722                         {
6723                                 // declare variables
6724                                 float blur_factor, blur_mouseaccel, blur_velocity;
6725                                 static float blur_average; 
6726                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6727
6728                                 // set a goal for the factoring
6729                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6730                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6731                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6732                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6733                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6734                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6735
6736                                 // from the goal, pick an averaged value between goal and last value
6737                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6738                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6739
6740                                 // enforce minimum amount of blur 
6741                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6742
6743                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6744
6745                                 // calculate values into a standard alpha
6746                                 cl.motionbluralpha = 1 - exp(-
6747                                                 (
6748                                                  (r_motionblur.value * blur_factor / 80)
6749                                                  +
6750                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6751                                                 )
6752                                                 /
6753                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6754                                           );
6755
6756                                 // randomization for the blur value to combat persistent ghosting
6757                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6758                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6759
6760                                 // apply the blur
6761                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6762                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6763                                 {
6764                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6765                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6766                                         switch(vid.renderpath)
6767                                         {
6768                                         case RENDERPATH_GL11:
6769                                         case RENDERPATH_GL13:
6770                                         case RENDERPATH_GL20:
6771                                         case RENDERPATH_GLES1:
6772                                         case RENDERPATH_GLES2:
6773                                         case RENDERPATH_SOFT:
6774                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6775                                                 break;
6776                                         case RENDERPATH_D3D9:
6777                                         case RENDERPATH_D3D10:
6778                                         case RENDERPATH_D3D11:
6779                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6780                                                 break;
6781                                         }
6782                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6783                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6784                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6785                                 }
6786
6787                                 // updates old view angles for next pass
6788                                 VectorCopy(cl.viewangles, blur_oldangles);
6789
6790                                 // copy view into the ghost texture
6791                                 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);
6792                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6793                                 r_fb.ghosttexture_valid = true;
6794                         }
6795                 }
6796                 else
6797                 {
6798                         // no r_fb.colortexture means we're rendering to the real fb
6799                         // we may still have to do view tint...
6800                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6801                         {
6802                                 // apply a color tint to the whole view
6803                                 R_ResetViewRendering2D(0, NULL, NULL);
6804                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6805                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6806                                 R_SetupShader_Generic_NoTexture(false, true);
6807                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6808                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6809                         }
6810                         break; // no screen processing, no bloom, skip it
6811                 }
6812
6813                 if (r_fb.bloomtexture[0])
6814                 {
6815                         // make the bloom texture
6816                         R_Bloom_MakeTexture();
6817                 }
6818
6819 #if _MSC_VER >= 1400
6820 #define sscanf sscanf_s
6821 #endif
6822                 memset(uservecs, 0, sizeof(uservecs));
6823                 if (r_glsl_postprocess_uservec1_enable.integer)
6824                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6825                 if (r_glsl_postprocess_uservec2_enable.integer)
6826                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6827                 if (r_glsl_postprocess_uservec3_enable.integer)
6828                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6829                 if (r_glsl_postprocess_uservec4_enable.integer)
6830                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6831
6832                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6833                 GL_Color(1, 1, 1, 1);
6834                 GL_BlendFunc(GL_ONE, GL_ZERO);
6835
6836                 switch(vid.renderpath)
6837                 {
6838                 case RENDERPATH_GL20:
6839                 case RENDERPATH_GLES2:
6840                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6841                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6842                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6843                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6844                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6845                         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]);
6846                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6847                         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]);
6848                         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]);
6849                         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]);
6850                         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]);
6851                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6852                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6853                         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);
6854                         break;
6855                 case RENDERPATH_D3D9:
6856 #ifdef SUPPORTD3D
6857                         // 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...
6858                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6859                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6860                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6861                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6862                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6863                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6864                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6865                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6866                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6867                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6868                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6869                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6870                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6871                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6872 #endif
6873                         break;
6874                 case RENDERPATH_D3D10:
6875                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6876                         break;
6877                 case RENDERPATH_D3D11:
6878                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6879                         break;
6880                 case RENDERPATH_SOFT:
6881                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6882                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6883                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6884                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6885                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6886                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6887                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6888                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6889                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6890                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6891                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6892                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6893                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6894                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6895                         break;
6896                 default:
6897                         break;
6898                 }
6899                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6900                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6901                 break;
6902         case RENDERPATH_GL11:
6903         case RENDERPATH_GL13:
6904         case RENDERPATH_GLES1:
6905                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6906                 {
6907                         // apply a color tint to the whole view
6908                         R_ResetViewRendering2D(0, NULL, NULL);
6909                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6910                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6911                         R_SetupShader_Generic_NoTexture(false, true);
6912                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6913                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6914                 }
6915                 break;
6916         }
6917 }
6918
6919 matrix4x4_t r_waterscrollmatrix;
6920
6921 void R_UpdateFog(void)
6922 {
6923         // Nehahra fog
6924         if (gamemode == GAME_NEHAHRA)
6925         {
6926                 if (gl_fogenable.integer)
6927                 {
6928                         r_refdef.oldgl_fogenable = true;
6929                         r_refdef.fog_density = gl_fogdensity.value;
6930                         r_refdef.fog_red = gl_fogred.value;
6931                         r_refdef.fog_green = gl_foggreen.value;
6932                         r_refdef.fog_blue = gl_fogblue.value;
6933                         r_refdef.fog_alpha = 1;
6934                         r_refdef.fog_start = 0;
6935                         r_refdef.fog_end = gl_skyclip.value;
6936                         r_refdef.fog_height = 1<<30;
6937                         r_refdef.fog_fadedepth = 128;
6938                 }
6939                 else if (r_refdef.oldgl_fogenable)
6940                 {
6941                         r_refdef.oldgl_fogenable = false;
6942                         r_refdef.fog_density = 0;
6943                         r_refdef.fog_red = 0;
6944                         r_refdef.fog_green = 0;
6945                         r_refdef.fog_blue = 0;
6946                         r_refdef.fog_alpha = 0;
6947                         r_refdef.fog_start = 0;
6948                         r_refdef.fog_end = 0;
6949                         r_refdef.fog_height = 1<<30;
6950                         r_refdef.fog_fadedepth = 128;
6951                 }
6952         }
6953
6954         // fog parms
6955         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6956         r_refdef.fog_start = max(0, r_refdef.fog_start);
6957         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6958
6959         if (r_refdef.fog_density && r_drawfog.integer)
6960         {
6961                 r_refdef.fogenabled = true;
6962                 // this is the point where the fog reaches 0.9986 alpha, which we
6963                 // consider a good enough cutoff point for the texture
6964                 // (0.9986 * 256 == 255.6)
6965                 if (r_fog_exp2.integer)
6966                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6967                 else
6968                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6969                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6970                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6971                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6972                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6973                         R_BuildFogHeightTexture();
6974                 // fog color was already set
6975                 // update the fog texture
6976                 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)
6977                         R_BuildFogTexture();
6978                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6979                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6980         }
6981         else
6982                 r_refdef.fogenabled = false;
6983
6984         // fog color
6985         if (r_refdef.fog_density)
6986         {
6987                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6988                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6989                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6990
6991                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6992                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6993                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6994                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6995
6996                 {
6997                         vec3_t fogvec;
6998                         VectorCopy(r_refdef.fogcolor, fogvec);
6999                         //   color.rgb *= ContrastBoost * SceneBrightness;
7000                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7001                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7002                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7003                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7004                 }
7005         }
7006 }
7007
7008 void R_UpdateVariables(void)
7009 {
7010         R_Textures_Frame();
7011
7012         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7013
7014         r_refdef.farclip = r_farclip_base.value;
7015         if (r_refdef.scene.worldmodel)
7016                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7017         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7018
7019         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7020                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7021         r_refdef.polygonfactor = 0;
7022         r_refdef.polygonoffset = 0;
7023         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7024         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7025
7026         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7027         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7028         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7029         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7030         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7031         if (FAKELIGHT_ENABLED)
7032         {
7033                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7034         }
7035         else if (r_refdef.scene.worldmodel)
7036         {
7037                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7038         }
7039         if (r_showsurfaces.integer)
7040         {
7041                 r_refdef.scene.rtworld = false;
7042                 r_refdef.scene.rtworldshadows = false;
7043                 r_refdef.scene.rtdlight = false;
7044                 r_refdef.scene.rtdlightshadows = false;
7045                 r_refdef.lightmapintensity = 0;
7046         }
7047
7048         r_gpuskeletal = false;
7049         switch(vid.renderpath)
7050         {
7051         case RENDERPATH_GL20:
7052                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7053         case RENDERPATH_D3D9:
7054         case RENDERPATH_D3D10:
7055         case RENDERPATH_D3D11:
7056         case RENDERPATH_SOFT:
7057         case RENDERPATH_GLES2:
7058                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7059                 {
7060                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7061                         {
7062                                 // build GLSL gamma texture
7063 #define RAMPWIDTH 256
7064                                 unsigned short ramp[RAMPWIDTH * 3];
7065                                 unsigned char rampbgr[RAMPWIDTH][4];
7066                                 int i;
7067
7068                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7069
7070                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7071                                 for(i = 0; i < RAMPWIDTH; ++i)
7072                                 {
7073                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7074                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7075                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7076                                         rampbgr[i][3] = 0;
7077                                 }
7078                                 if (r_texture_gammaramps)
7079                                 {
7080                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7081                                 }
7082                                 else
7083                                 {
7084                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7085                                 }
7086                         }
7087                 }
7088                 else
7089                 {
7090                         // remove GLSL gamma texture
7091                 }
7092                 break;
7093         case RENDERPATH_GL11:
7094         case RENDERPATH_GL13:
7095         case RENDERPATH_GLES1:
7096                 break;
7097         }
7098 }
7099
7100 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7101 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7102 /*
7103 ================
7104 R_SelectScene
7105 ================
7106 */
7107 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7108         if( scenetype != r_currentscenetype ) {
7109                 // store the old scenetype
7110                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7111                 r_currentscenetype = scenetype;
7112                 // move in the new scene
7113                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7114         }
7115 }
7116
7117 /*
7118 ================
7119 R_GetScenePointer
7120 ================
7121 */
7122 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7123 {
7124         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7125         if( scenetype == r_currentscenetype ) {
7126                 return &r_refdef.scene;
7127         } else {
7128                 return &r_scenes_store[ scenetype ];
7129         }
7130 }
7131
7132 static int R_SortEntities_Compare(const void *ap, const void *bp)
7133 {
7134         const entity_render_t *a = *(const entity_render_t **)ap;
7135         const entity_render_t *b = *(const entity_render_t **)bp;
7136
7137         // 1. compare model
7138         if(a->model < b->model)
7139                 return -1;
7140         if(a->model > b->model)
7141                 return +1;
7142
7143         // 2. compare skin
7144         // TODO possibly calculate the REAL skinnum here first using
7145         // skinscenes?
7146         if(a->skinnum < b->skinnum)
7147                 return -1;
7148         if(a->skinnum > b->skinnum)
7149                 return +1;
7150
7151         // everything we compared is equal
7152         return 0;
7153 }
7154 static void R_SortEntities(void)
7155 {
7156         // below or equal 2 ents, sorting never gains anything
7157         if(r_refdef.scene.numentities <= 2)
7158                 return;
7159         // sort
7160         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7161 }
7162
7163 /*
7164 ================
7165 R_RenderView
7166 ================
7167 */
7168 int dpsoftrast_test;
7169 extern cvar_t r_shadow_bouncegrid;
7170 void R_RenderView(void)
7171 {
7172         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7173         int fbo;
7174         rtexture_t *depthtexture;
7175         rtexture_t *colortexture;
7176
7177         dpsoftrast_test = r_test.integer;
7178
7179         if (r_timereport_active)
7180                 R_TimeReport("start");
7181         r_textureframe++; // used only by R_GetCurrentTexture
7182         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7183
7184         if(R_CompileShader_CheckStaticParms())
7185                 R_GLSL_Restart_f();
7186
7187         if (!r_drawentities.integer)
7188                 r_refdef.scene.numentities = 0;
7189         else if (r_sortentities.integer)
7190                 R_SortEntities();
7191
7192         R_AnimCache_ClearCache();
7193
7194         /* adjust for stereo display */
7195         if(R_Stereo_Active())
7196         {
7197                 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);
7198                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7199         }
7200
7201         if (r_refdef.view.isoverlay)
7202         {
7203                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7204                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7205                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7206                 R_TimeReport("depthclear");
7207
7208                 r_refdef.view.showdebug = false;
7209
7210                 r_fb.water.enabled = false;
7211                 r_fb.water.numwaterplanes = 0;
7212
7213                 R_RenderScene(0, NULL, NULL);
7214
7215                 r_refdef.view.matrix = originalmatrix;
7216
7217                 CHECKGLERROR
7218                 return;
7219         }
7220
7221         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7222         {
7223                 r_refdef.view.matrix = originalmatrix;
7224                 return;
7225         }
7226
7227         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7228
7229         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7230                 // in sRGB fallback, behave similar to true sRGB: convert this
7231                 // value from linear to sRGB
7232                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7233
7234         R_RenderView_UpdateViewVectors();
7235
7236         R_Shadow_UpdateWorldLightSelection();
7237
7238         R_Bloom_StartFrame();
7239
7240         // apply bloom brightness offset
7241         if(r_fb.bloomtexture[0])
7242                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7243
7244         R_Water_StartFrame();
7245
7246         // now we probably have an fbo to render into
7247         fbo = r_fb.fbo;
7248         depthtexture = r_fb.depthtexture;
7249         colortexture = r_fb.colortexture;
7250
7251         CHECKGLERROR
7252         if (r_timereport_active)
7253                 R_TimeReport("viewsetup");
7254
7255         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7256
7257         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7258         {
7259                 R_ClearScreen(r_refdef.fogenabled);
7260                 if (r_timereport_active)
7261                         R_TimeReport("viewclear");
7262         }
7263         r_refdef.view.clear = true;
7264
7265         r_refdef.view.showdebug = true;
7266
7267         R_View_Update();
7268         if (r_timereport_active)
7269                 R_TimeReport("visibility");
7270
7271         R_AnimCache_CacheVisibleEntities();
7272         if (r_timereport_active)
7273                 R_TimeReport("animcache");
7274
7275         R_Shadow_UpdateBounceGridTexture();
7276         if (r_timereport_active && r_shadow_bouncegrid.integer)
7277                 R_TimeReport("bouncegrid");
7278
7279         r_fb.water.numwaterplanes = 0;
7280         if (r_fb.water.enabled)
7281                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7282
7283         R_RenderScene(fbo, depthtexture, colortexture);
7284         r_fb.water.numwaterplanes = 0;
7285
7286         R_BlendView(fbo, depthtexture, colortexture);
7287         if (r_timereport_active)
7288                 R_TimeReport("blendview");
7289
7290         GL_Scissor(0, 0, vid.width, vid.height);
7291         GL_ScissorTest(false);
7292
7293         r_refdef.view.matrix = originalmatrix;
7294
7295         CHECKGLERROR
7296 }
7297
7298 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7299 {
7300         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7301         {
7302                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7303                 if (r_timereport_active)
7304                         R_TimeReport("waterworld");
7305         }
7306
7307         // don't let sound skip if going slow
7308         if (r_refdef.scene.extraupdate)
7309                 S_ExtraUpdate ();
7310
7311         R_DrawModelsAddWaterPlanes();
7312         if (r_timereport_active)
7313                 R_TimeReport("watermodels");
7314
7315         if (r_fb.water.numwaterplanes)
7316         {
7317                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7318                 if (r_timereport_active)
7319                         R_TimeReport("waterscenes");
7320         }
7321 }
7322
7323 extern cvar_t cl_locs_show;
7324 static void R_DrawLocs(void);
7325 static void R_DrawEntityBBoxes(void);
7326 static void R_DrawModelDecals(void);
7327 extern cvar_t cl_decals_newsystem;
7328 extern qboolean r_shadow_usingdeferredprepass;
7329 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7330 {
7331         qboolean shadowmapping = false;
7332
7333         if (r_timereport_active)
7334                 R_TimeReport("beginscene");
7335
7336         r_refdef.stats[r_stat_renders]++;
7337
7338         R_UpdateFog();
7339
7340         // don't let sound skip if going slow
7341         if (r_refdef.scene.extraupdate)
7342                 S_ExtraUpdate ();
7343
7344         R_MeshQueue_BeginScene();
7345
7346         R_SkyStartFrame();
7347
7348         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);
7349
7350         if (r_timereport_active)
7351                 R_TimeReport("skystartframe");
7352
7353         if (cl.csqc_vidvars.drawworld)
7354         {
7355                 // don't let sound skip if going slow
7356                 if (r_refdef.scene.extraupdate)
7357                         S_ExtraUpdate ();
7358
7359                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7360                 {
7361                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7362                         if (r_timereport_active)
7363                                 R_TimeReport("worldsky");
7364                 }
7365
7366                 if (R_DrawBrushModelsSky() && r_timereport_active)
7367                         R_TimeReport("bmodelsky");
7368
7369                 if (skyrendermasked && skyrenderlater)
7370                 {
7371                         // we have to force off the water clipping plane while rendering sky
7372                         R_SetupView(false, fbo, depthtexture, colortexture);
7373                         R_Sky();
7374                         R_SetupView(true, fbo, depthtexture, colortexture);
7375                         if (r_timereport_active)
7376                                 R_TimeReport("sky");
7377                 }
7378         }
7379
7380         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7381         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7382                 R_Shadow_PrepareModelShadows();
7383         if (r_timereport_active)
7384                 R_TimeReport("preparelights");
7385
7386         if (R_Shadow_ShadowMappingEnabled())
7387                 shadowmapping = true;
7388
7389         if (r_shadow_usingdeferredprepass)
7390                 R_Shadow_DrawPrepass();
7391
7392         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7393         {
7394                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7395                 if (r_timereport_active)
7396                         R_TimeReport("worlddepth");
7397         }
7398         if (r_depthfirst.integer >= 2)
7399         {
7400                 R_DrawModelsDepth();
7401                 if (r_timereport_active)
7402                         R_TimeReport("modeldepth");
7403         }
7404
7405         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7406         {
7407                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7408                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7409                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7410                 // don't let sound skip if going slow
7411                 if (r_refdef.scene.extraupdate)
7412                         S_ExtraUpdate ();
7413         }
7414
7415         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7416         {
7417                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7418                 if (r_timereport_active)
7419                         R_TimeReport("world");
7420         }
7421
7422         // don't let sound skip if going slow
7423         if (r_refdef.scene.extraupdate)
7424                 S_ExtraUpdate ();
7425
7426         R_DrawModels();
7427         if (r_timereport_active)
7428                 R_TimeReport("models");
7429
7430         // don't let sound skip if going slow
7431         if (r_refdef.scene.extraupdate)
7432                 S_ExtraUpdate ();
7433
7434         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7435         {
7436                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7437                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7438                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7439                 // don't let sound skip if going slow
7440                 if (r_refdef.scene.extraupdate)
7441                         S_ExtraUpdate ();
7442         }
7443
7444         if (!r_shadow_usingdeferredprepass)
7445         {
7446                 R_Shadow_DrawLights();
7447                 if (r_timereport_active)
7448                         R_TimeReport("rtlights");
7449         }
7450
7451         // don't let sound skip if going slow
7452         if (r_refdef.scene.extraupdate)
7453                 S_ExtraUpdate ();
7454
7455         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7456         {
7457                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7458                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7459                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7460                 // don't let sound skip if going slow
7461                 if (r_refdef.scene.extraupdate)
7462                         S_ExtraUpdate ();
7463         }
7464
7465         if (cl.csqc_vidvars.drawworld)
7466         {
7467                 if (cl_decals_newsystem.integer)
7468                 {
7469                         R_DrawModelDecals();
7470                         if (r_timereport_active)
7471                                 R_TimeReport("modeldecals");
7472                 }
7473                 else
7474                 {
7475                         R_DrawDecals();
7476                         if (r_timereport_active)
7477                                 R_TimeReport("decals");
7478                 }
7479
7480                 R_DrawParticles();
7481                 if (r_timereport_active)
7482                         R_TimeReport("particles");
7483
7484                 R_DrawExplosions();
7485                 if (r_timereport_active)
7486                         R_TimeReport("explosions");
7487
7488                 R_DrawLightningBeams();
7489                 if (r_timereport_active)
7490                         R_TimeReport("lightning");
7491         }
7492
7493         if (cl.csqc_loaded)
7494                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7495
7496         if (r_refdef.view.showdebug)
7497         {
7498                 if (cl_locs_show.integer)
7499                 {
7500                         R_DrawLocs();
7501                         if (r_timereport_active)
7502                                 R_TimeReport("showlocs");
7503                 }
7504
7505                 if (r_drawportals.integer)
7506                 {
7507                         R_DrawPortals();
7508                         if (r_timereport_active)
7509                                 R_TimeReport("portals");
7510                 }
7511
7512                 if (r_showbboxes.value > 0)
7513                 {
7514                         R_DrawEntityBBoxes();
7515                         if (r_timereport_active)
7516                                 R_TimeReport("bboxes");
7517                 }
7518         }
7519
7520         if (r_transparent.integer)
7521         {
7522                 R_MeshQueue_RenderTransparent();
7523                 if (r_timereport_active)
7524                         R_TimeReport("drawtrans");
7525         }
7526
7527         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))
7528         {
7529                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7530                 if (r_timereport_active)
7531                         R_TimeReport("worlddebug");
7532                 R_DrawModelsDebug();
7533                 if (r_timereport_active)
7534                         R_TimeReport("modeldebug");
7535         }
7536
7537         if (cl.csqc_vidvars.drawworld)
7538         {
7539                 R_Shadow_DrawCoronas();
7540                 if (r_timereport_active)
7541                         R_TimeReport("coronas");
7542         }
7543
7544 #if 0
7545         {
7546                 GL_DepthTest(false);
7547                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7548                 GL_Color(1, 1, 1, 1);
7549                 qglBegin(GL_POLYGON);
7550                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7551                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7552                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7553                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7554                 qglEnd();
7555                 qglBegin(GL_POLYGON);
7556                 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]);
7557                 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]);
7558                 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]);
7559                 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]);
7560                 qglEnd();
7561                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7562         }
7563 #endif
7564
7565         // don't let sound skip if going slow
7566         if (r_refdef.scene.extraupdate)
7567                 S_ExtraUpdate ();
7568 }
7569
7570 static const unsigned short bboxelements[36] =
7571 {
7572         5, 1, 3, 5, 3, 7,
7573         6, 2, 0, 6, 0, 4,
7574         7, 3, 2, 7, 2, 6,
7575         4, 0, 1, 4, 1, 5,
7576         4, 5, 7, 4, 7, 6,
7577         1, 0, 2, 1, 2, 3,
7578 };
7579
7580 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7581 {
7582         int i;
7583         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7584
7585         RSurf_ActiveWorldEntity();
7586
7587         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7588         GL_DepthMask(false);
7589         GL_DepthRange(0, 1);
7590         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7591 //      R_Mesh_ResetTextureState();
7592
7593         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7594         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7595         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7596         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7597         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7598         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7599         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7600         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7601         R_FillColors(color4f, 8, cr, cg, cb, ca);
7602         if (r_refdef.fogenabled)
7603         {
7604                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7605                 {
7606                         f1 = RSurf_FogVertex(v);
7607                         f2 = 1 - f1;
7608                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7609                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7610                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7611                 }
7612         }
7613         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7614         R_Mesh_ResetTextureState();
7615         R_SetupShader_Generic_NoTexture(false, false);
7616         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7617 }
7618
7619 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7620 {
7621         prvm_prog_t *prog = SVVM_prog;
7622         int i;
7623         float color[4];
7624         prvm_edict_t *edict;
7625
7626         // this function draws bounding boxes of server entities
7627         if (!sv.active)
7628                 return;
7629
7630         GL_CullFace(GL_NONE);
7631         R_SetupShader_Generic_NoTexture(false, false);
7632
7633         for (i = 0;i < numsurfaces;i++)
7634         {
7635                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7636                 switch ((int)PRVM_serveredictfloat(edict, solid))
7637                 {
7638                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7639                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7640                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7641                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7642                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7643                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7644                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7645                 }
7646                 color[3] *= r_showbboxes.value;
7647                 color[3] = bound(0, color[3], 1);
7648                 GL_DepthTest(!r_showdisabledepthtest.integer);
7649                 GL_CullFace(r_refdef.view.cullface_front);
7650                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7651         }
7652 }
7653
7654 static void R_DrawEntityBBoxes(void)
7655 {
7656         int i;
7657         prvm_edict_t *edict;
7658         vec3_t center;
7659         prvm_prog_t *prog = SVVM_prog;
7660
7661         // this function draws bounding boxes of server entities
7662         if (!sv.active)
7663                 return;
7664
7665         for (i = 0;i < prog->num_edicts;i++)
7666         {
7667                 edict = PRVM_EDICT_NUM(i);
7668                 if (edict->priv.server->free)
7669                         continue;
7670                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7671                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7672                         continue;
7673                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7674                         continue;
7675                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7676                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7677         }
7678 }
7679
7680 static const int nomodelelement3i[24] =
7681 {
7682         5, 2, 0,
7683         5, 1, 2,
7684         5, 0, 3,
7685         5, 3, 1,
7686         0, 2, 4,
7687         2, 1, 4,
7688         3, 0, 4,
7689         1, 3, 4
7690 };
7691
7692 static const unsigned short nomodelelement3s[24] =
7693 {
7694         5, 2, 0,
7695         5, 1, 2,
7696         5, 0, 3,
7697         5, 3, 1,
7698         0, 2, 4,
7699         2, 1, 4,
7700         3, 0, 4,
7701         1, 3, 4
7702 };
7703
7704 static const float nomodelvertex3f[6*3] =
7705 {
7706         -16,   0,   0,
7707          16,   0,   0,
7708           0, -16,   0,
7709           0,  16,   0,
7710           0,   0, -16,
7711           0,   0,  16
7712 };
7713
7714 static const float nomodelcolor4f[6*4] =
7715 {
7716         0.0f, 0.0f, 0.5f, 1.0f,
7717         0.0f, 0.0f, 0.5f, 1.0f,
7718         0.0f, 0.5f, 0.0f, 1.0f,
7719         0.0f, 0.5f, 0.0f, 1.0f,
7720         0.5f, 0.0f, 0.0f, 1.0f,
7721         0.5f, 0.0f, 0.0f, 1.0f
7722 };
7723
7724 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7725 {
7726         int i;
7727         float f1, f2, *c;
7728         float color4f[6*4];
7729
7730         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);
7731
7732         // this is only called once per entity so numsurfaces is always 1, and
7733         // surfacelist is always {0}, so this code does not handle batches
7734
7735         if (rsurface.ent_flags & RENDER_ADDITIVE)
7736         {
7737                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7738                 GL_DepthMask(false);
7739         }
7740         else if (rsurface.colormod[3] < 1)
7741         {
7742                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7743                 GL_DepthMask(false);
7744         }
7745         else
7746         {
7747                 GL_BlendFunc(GL_ONE, GL_ZERO);
7748                 GL_DepthMask(true);
7749         }
7750         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7751         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7752         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7753         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7754         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7755         for (i = 0, c = color4f;i < 6;i++, c += 4)
7756         {
7757                 c[0] *= rsurface.colormod[0];
7758                 c[1] *= rsurface.colormod[1];
7759                 c[2] *= rsurface.colormod[2];
7760                 c[3] *= rsurface.colormod[3];
7761         }
7762         if (r_refdef.fogenabled)
7763         {
7764                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7765                 {
7766                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7767                         f2 = 1 - f1;
7768                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7769                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7770                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7771                 }
7772         }
7773 //      R_Mesh_ResetTextureState();
7774         R_SetupShader_Generic_NoTexture(false, false);
7775         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7776         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7777 }
7778
7779 void R_DrawNoModel(entity_render_t *ent)
7780 {
7781         vec3_t org;
7782         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7783         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7784                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7785         else
7786                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7787 }
7788
7789 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7790 {
7791         vec3_t right1, right2, diff, normal;
7792
7793         VectorSubtract (org2, org1, normal);
7794
7795         // calculate 'right' vector for start
7796         VectorSubtract (r_refdef.view.origin, org1, diff);
7797         CrossProduct (normal, diff, right1);
7798         VectorNormalize (right1);
7799
7800         // calculate 'right' vector for end
7801         VectorSubtract (r_refdef.view.origin, org2, diff);
7802         CrossProduct (normal, diff, right2);
7803         VectorNormalize (right2);
7804
7805         vert[ 0] = org1[0] + width * right1[0];
7806         vert[ 1] = org1[1] + width * right1[1];
7807         vert[ 2] = org1[2] + width * right1[2];
7808         vert[ 3] = org1[0] - width * right1[0];
7809         vert[ 4] = org1[1] - width * right1[1];
7810         vert[ 5] = org1[2] - width * right1[2];
7811         vert[ 6] = org2[0] - width * right2[0];
7812         vert[ 7] = org2[1] - width * right2[1];
7813         vert[ 8] = org2[2] - width * right2[2];
7814         vert[ 9] = org2[0] + width * right2[0];
7815         vert[10] = org2[1] + width * right2[1];
7816         vert[11] = org2[2] + width * right2[2];
7817 }
7818
7819 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)
7820 {
7821         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7822         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7823         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7824         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7825         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7826         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7827         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7828         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7829         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7830         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7831         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7832         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7833 }
7834
7835 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7836 {
7837         int i;
7838         float *vertex3f;
7839         float v[3];
7840         VectorSet(v, x, y, z);
7841         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7842                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7843                         break;
7844         if (i == mesh->numvertices)
7845         {
7846                 if (mesh->numvertices < mesh->maxvertices)
7847                 {
7848                         VectorCopy(v, vertex3f);
7849                         mesh->numvertices++;
7850                 }
7851                 return mesh->numvertices;
7852         }
7853         else
7854                 return i;
7855 }
7856
7857 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7858 {
7859         int i;
7860         int *e, element[3];
7861         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7862         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7863         e = mesh->element3i + mesh->numtriangles * 3;
7864         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7865         {
7866                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7867                 if (mesh->numtriangles < mesh->maxtriangles)
7868                 {
7869                         *e++ = element[0];
7870                         *e++ = element[1];
7871                         *e++ = element[2];
7872                         mesh->numtriangles++;
7873                 }
7874                 element[1] = element[2];
7875         }
7876 }
7877
7878 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7879 {
7880         int i;
7881         int *e, element[3];
7882         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7883         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7884         e = mesh->element3i + mesh->numtriangles * 3;
7885         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7886         {
7887                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7888                 if (mesh->numtriangles < mesh->maxtriangles)
7889                 {
7890                         *e++ = element[0];
7891                         *e++ = element[1];
7892                         *e++ = element[2];
7893                         mesh->numtriangles++;
7894                 }
7895                 element[1] = element[2];
7896         }
7897 }
7898
7899 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7900 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7901 {
7902         int planenum, planenum2;
7903         int w;
7904         int tempnumpoints;
7905         mplane_t *plane, *plane2;
7906         double maxdist;
7907         double temppoints[2][256*3];
7908         // figure out how large a bounding box we need to properly compute this brush
7909         maxdist = 0;
7910         for (w = 0;w < numplanes;w++)
7911                 maxdist = max(maxdist, fabs(planes[w].dist));
7912         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7913         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7914         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7915         {
7916                 w = 0;
7917                 tempnumpoints = 4;
7918                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7919                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7920                 {
7921                         if (planenum2 == planenum)
7922                                 continue;
7923                         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);
7924                         w = !w;
7925                 }
7926                 if (tempnumpoints < 3)
7927                         continue;
7928                 // generate elements forming a triangle fan for this polygon
7929                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7930         }
7931 }
7932
7933 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)
7934 {
7935         texturelayer_t *layer;
7936         layer = t->currentlayers + t->currentnumlayers++;
7937         layer->type = type;
7938         layer->depthmask = depthmask;
7939         layer->blendfunc1 = blendfunc1;
7940         layer->blendfunc2 = blendfunc2;
7941         layer->texture = texture;
7942         layer->texmatrix = *matrix;
7943         layer->color[0] = r;
7944         layer->color[1] = g;
7945         layer->color[2] = b;
7946         layer->color[3] = a;
7947 }
7948
7949 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7950 {
7951         if(parms[0] == 0 && parms[1] == 0)
7952                 return false;
7953         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7954                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7955                         return false;
7956         return true;
7957 }
7958
7959 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7960 {
7961         double index, f;
7962         index = parms[2] + rsurface.shadertime * parms[3];
7963         index -= floor(index);
7964         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7965         {
7966         default:
7967         case Q3WAVEFUNC_NONE:
7968         case Q3WAVEFUNC_NOISE:
7969         case Q3WAVEFUNC_COUNT:
7970                 f = 0;
7971                 break;
7972         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7973         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7974         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7975         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7976         case Q3WAVEFUNC_TRIANGLE:
7977                 index *= 4;
7978                 f = index - floor(index);
7979                 if (index < 1)
7980                 {
7981                         // f = f;
7982                 }
7983                 else if (index < 2)
7984                         f = 1 - f;
7985                 else if (index < 3)
7986                         f = -f;
7987                 else
7988                         f = -(1 - f);
7989                 break;
7990         }
7991         f = parms[0] + parms[1] * f;
7992         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7993                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7994         return (float) f;
7995 }
7996
7997 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7998 {
7999         int w, h, idx;
8000         double f;
8001         double offsetd[2];
8002         float tcmat[12];
8003         matrix4x4_t matrix, temp;
8004         switch(tcmod->tcmod)
8005         {
8006                 case Q3TCMOD_COUNT:
8007                 case Q3TCMOD_NONE:
8008                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8009                                 matrix = r_waterscrollmatrix;
8010                         else
8011                                 matrix = identitymatrix;
8012                         break;
8013                 case Q3TCMOD_ENTITYTRANSLATE:
8014                         // this is used in Q3 to allow the gamecode to control texcoord
8015                         // scrolling on the entity, which is not supported in darkplaces yet.
8016                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8017                         break;
8018                 case Q3TCMOD_ROTATE:
8019                         f = tcmod->parms[0] * rsurface.shadertime;
8020                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8021                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
8022                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8023                         break;
8024                 case Q3TCMOD_SCALE:
8025                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8026                         break;
8027                 case Q3TCMOD_SCROLL:
8028                         // extra care is needed because of precision breakdown with large values of time
8029                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8030                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8031                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8032                         break;
8033                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8034                         w = (int) tcmod->parms[0];
8035                         h = (int) tcmod->parms[1];
8036                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8037                         f = f - floor(f);
8038                         idx = (int) floor(f * w * h);
8039                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8040                         break;
8041                 case Q3TCMOD_STRETCH:
8042                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8043                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8044                         break;
8045                 case Q3TCMOD_TRANSFORM:
8046                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8047                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8048                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8049                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8050                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8051                         break;
8052                 case Q3TCMOD_TURBULENT:
8053                         // this is handled in the RSurf_PrepareVertices function
8054                         matrix = identitymatrix;
8055                         break;
8056         }
8057         temp = *texmatrix;
8058         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8059 }
8060
8061 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8062 {
8063         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8064         char name[MAX_QPATH];
8065         skinframe_t *skinframe;
8066         unsigned char pixels[296*194];
8067         strlcpy(cache->name, skinname, sizeof(cache->name));
8068         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8069         if (developer_loading.integer)
8070                 Con_Printf("loading %s\n", name);
8071         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8072         if (!skinframe || !skinframe->base)
8073         {
8074                 unsigned char *f;
8075                 fs_offset_t filesize;
8076                 skinframe = NULL;
8077                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8078                 if (f)
8079                 {
8080                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8081                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8082                         Mem_Free(f);
8083                 }
8084         }
8085         cache->skinframe = skinframe;
8086 }
8087
8088 texture_t *R_GetCurrentTexture(texture_t *t)
8089 {
8090         int i;
8091         const entity_render_t *ent = rsurface.entity;
8092         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8093         q3shaderinfo_layer_tcmod_t *tcmod;
8094
8095         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8096                 return t->currentframe;
8097         t->update_lastrenderframe = r_textureframe;
8098         t->update_lastrenderentity = (void *)ent;
8099
8100         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8101                 t->camera_entity = ent->entitynumber;
8102         else
8103                 t->camera_entity = 0;
8104
8105         // switch to an alternate material if this is a q1bsp animated material
8106         {
8107                 texture_t *texture = t;
8108                 int s = rsurface.ent_skinnum;
8109                 if ((unsigned int)s >= (unsigned int)model->numskins)
8110                         s = 0;
8111                 if (model->skinscenes)
8112                 {
8113                         if (model->skinscenes[s].framecount > 1)
8114                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8115                         else
8116                                 s = model->skinscenes[s].firstframe;
8117                 }
8118                 if (s > 0)
8119                         t = t + s * model->num_surfaces;
8120                 if (t->animated)
8121                 {
8122                         // use an alternate animation if the entity's frame is not 0,
8123                         // and only if the texture has an alternate animation
8124                         if (rsurface.ent_alttextures && t->anim_total[1])
8125                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8126                         else
8127                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8128                 }
8129                 texture->currentframe = t;
8130         }
8131
8132         // update currentskinframe to be a qw skin or animation frame
8133         if (rsurface.ent_qwskin >= 0)
8134         {
8135                 i = rsurface.ent_qwskin;
8136                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8137                 {
8138                         r_qwskincache_size = cl.maxclients;
8139                         if (r_qwskincache)
8140                                 Mem_Free(r_qwskincache);
8141                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8142                 }
8143                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8144                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8145                 t->currentskinframe = r_qwskincache[i].skinframe;
8146                 if (t->currentskinframe == NULL)
8147                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8148         }
8149         else if (t->numskinframes >= 2)
8150                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8151         if (t->backgroundnumskinframes >= 2)
8152                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8153
8154         t->currentmaterialflags = t->basematerialflags;
8155         t->currentalpha = rsurface.colormod[3];
8156         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8157                 t->currentalpha *= r_wateralpha.value;
8158         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8159                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8160         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8161                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8162         if (!(rsurface.ent_flags & RENDER_LIGHT))
8163                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8164         else if (FAKELIGHT_ENABLED)
8165         {
8166                 // no modellight if using fakelight for the map
8167         }
8168         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8169         {
8170                 // pick a model lighting mode
8171                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8172                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8173                 else
8174                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8175         }
8176         if (rsurface.ent_flags & RENDER_ADDITIVE)
8177                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8178         else if (t->currentalpha < 1)
8179                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8180         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8181         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8182                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8183         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8184                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8185         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8186                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8187         if (t->backgroundnumskinframes)
8188                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8189         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8190         {
8191                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8192                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8193         }
8194         else
8195                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8196         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8197         {
8198                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8199                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8200         }
8201         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8202                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8203
8204         // there is no tcmod
8205         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8206         {
8207                 t->currenttexmatrix = r_waterscrollmatrix;
8208                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8209         }
8210         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8211         {
8212                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8213                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8214         }
8215
8216         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8217                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8218         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8219                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8220
8221         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8222         if (t->currentskinframe->qpixels)
8223                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8224         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8225         if (!t->basetexture)
8226                 t->basetexture = r_texture_notexture;
8227         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8228         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8229         t->nmaptexture = t->currentskinframe->nmap;
8230         if (!t->nmaptexture)
8231                 t->nmaptexture = r_texture_blanknormalmap;
8232         t->glosstexture = r_texture_black;
8233         t->glowtexture = t->currentskinframe->glow;
8234         t->fogtexture = t->currentskinframe->fog;
8235         t->reflectmasktexture = t->currentskinframe->reflect;
8236         if (t->backgroundnumskinframes)
8237         {
8238                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8239                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8240                 t->backgroundglosstexture = r_texture_black;
8241                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8242                 if (!t->backgroundnmaptexture)
8243                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8244                 // make sure that if glow is going to be used, both textures are not NULL
8245                 if (!t->backgroundglowtexture && t->glowtexture)
8246                         t->backgroundglowtexture = r_texture_black;
8247                 if (!t->glowtexture && t->backgroundglowtexture)
8248                         t->glowtexture = r_texture_black;
8249         }
8250         else
8251         {
8252                 t->backgroundbasetexture = r_texture_white;
8253                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8254                 t->backgroundglosstexture = r_texture_black;
8255                 t->backgroundglowtexture = NULL;
8256         }
8257         t->specularpower = r_shadow_glossexponent.value;
8258         // TODO: store reference values for these in the texture?
8259         t->specularscale = 0;
8260         if (r_shadow_gloss.integer > 0)
8261         {
8262                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8263                 {
8264                         if (r_shadow_glossintensity.value > 0)
8265                         {
8266                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8267                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8268                                 t->specularscale = r_shadow_glossintensity.value;
8269                         }
8270                 }
8271                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8272                 {
8273                         t->glosstexture = r_texture_white;
8274                         t->backgroundglosstexture = r_texture_white;
8275                         t->specularscale = r_shadow_gloss2intensity.value;
8276                         t->specularpower = r_shadow_gloss2exponent.value;
8277                 }
8278         }
8279         t->specularscale *= t->specularscalemod;
8280         t->specularpower *= t->specularpowermod;
8281         t->rtlightambient = 0;
8282
8283         // lightmaps mode looks bad with dlights using actual texturing, so turn
8284         // off the colormap and glossmap, but leave the normalmap on as it still
8285         // accurately represents the shading involved
8286         if (gl_lightmaps.integer)
8287         {
8288                 t->basetexture = r_texture_grey128;
8289                 t->pantstexture = r_texture_black;
8290                 t->shirttexture = r_texture_black;
8291                 if (gl_lightmaps.integer < 2)
8292                         t->nmaptexture = r_texture_blanknormalmap;
8293                 t->glosstexture = r_texture_black;
8294                 t->glowtexture = NULL;
8295                 t->fogtexture = NULL;
8296                 t->reflectmasktexture = NULL;
8297                 t->backgroundbasetexture = NULL;
8298                 if (gl_lightmaps.integer < 2)
8299                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8300                 t->backgroundglosstexture = r_texture_black;
8301                 t->backgroundglowtexture = NULL;
8302                 t->specularscale = 0;
8303                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8304         }
8305
8306         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8307         VectorClear(t->dlightcolor);
8308         t->currentnumlayers = 0;
8309         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8310         {
8311                 int blendfunc1, blendfunc2;
8312                 qboolean depthmask;
8313                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8314                 {
8315                         blendfunc1 = GL_SRC_ALPHA;
8316                         blendfunc2 = GL_ONE;
8317                 }
8318                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8319                 {
8320                         blendfunc1 = GL_SRC_ALPHA;
8321                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8322                 }
8323                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8324                 {
8325                         blendfunc1 = t->customblendfunc[0];
8326                         blendfunc2 = t->customblendfunc[1];
8327                 }
8328                 else
8329                 {
8330                         blendfunc1 = GL_ONE;
8331                         blendfunc2 = GL_ZERO;
8332                 }
8333                 // don't colormod evilblend textures
8334                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8335                         VectorSet(t->lightmapcolor, 1, 1, 1);
8336                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8337                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8338                 {
8339                         // fullbright is not affected by r_refdef.lightmapintensity
8340                         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]);
8341                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8342                                 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]);
8343                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8344                                 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]);
8345                 }
8346                 else
8347                 {
8348                         vec3_t ambientcolor;
8349                         float colorscale;
8350                         // set the color tint used for lights affecting this surface
8351                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8352                         colorscale = 2;
8353                         // q3bsp has no lightmap updates, so the lightstylevalue that
8354                         // would normally be baked into the lightmap must be
8355                         // applied to the color
8356                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8357                         if (model->type == mod_brushq3)
8358                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8359                         colorscale *= r_refdef.lightmapintensity;
8360                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8361                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8362                         // basic lit geometry
8363                         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]);
8364                         // add pants/shirt if needed
8365                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8366                                 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]);
8367                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8368                                 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]);
8369                         // now add ambient passes if needed
8370                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8371                         {
8372                                 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]);
8373                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8374                                         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]);
8375                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8376                                         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]);
8377                         }
8378                 }
8379                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8380                         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]);
8381                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8382                 {
8383                         // if this is opaque use alpha blend which will darken the earlier
8384                         // passes cheaply.
8385                         //
8386                         // if this is an alpha blended material, all the earlier passes
8387                         // were darkened by fog already, so we only need to add the fog
8388                         // color ontop through the fog mask texture
8389                         //
8390                         // if this is an additive blended material, all the earlier passes
8391                         // were darkened by fog already, and we should not add fog color
8392                         // (because the background was not darkened, there is no fog color
8393                         // that was lost behind it).
8394                         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]);
8395                 }
8396         }
8397
8398         return t->currentframe;
8399 }
8400
8401 rsurfacestate_t rsurface;
8402
8403 void RSurf_ActiveWorldEntity(void)
8404 {
8405         dp_model_t *model = r_refdef.scene.worldmodel;
8406         //if (rsurface.entity == r_refdef.scene.worldentity)
8407         //      return;
8408         rsurface.entity = r_refdef.scene.worldentity;
8409         rsurface.skeleton = NULL;
8410         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8411         rsurface.ent_skinnum = 0;
8412         rsurface.ent_qwskin = -1;
8413         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8414         rsurface.shadertime = r_refdef.scene.time;
8415         rsurface.matrix = identitymatrix;
8416         rsurface.inversematrix = identitymatrix;
8417         rsurface.matrixscale = 1;
8418         rsurface.inversematrixscale = 1;
8419         R_EntityMatrix(&identitymatrix);
8420         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8421         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8422         rsurface.fograngerecip = r_refdef.fograngerecip;
8423         rsurface.fogheightfade = r_refdef.fogheightfade;
8424         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8425         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8426         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8427         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8428         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8429         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8430         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8431         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8432         rsurface.colormod[3] = 1;
8433         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);
8434         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8435         rsurface.frameblend[0].lerp = 1;
8436         rsurface.ent_alttextures = false;
8437         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8438         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8439         rsurface.entityskeletaltransform3x4 = NULL;
8440         rsurface.entityskeletaltransform3x4buffer = NULL;
8441         rsurface.entityskeletaltransform3x4offset = 0;
8442         rsurface.entityskeletaltransform3x4size = 0;;
8443         rsurface.entityskeletalnumtransforms = 0;
8444         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8445         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8446         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8447         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8448         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8449         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8450         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8451         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8452         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8453         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8454         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8455         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8456         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8457         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8458         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8459         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8460         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8461         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8462         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8463         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8464         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8465         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8466         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8467         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8468         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8469         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8470         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8471         rsurface.modelelement3i = model->surfmesh.data_element3i;
8472         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8473         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8474         rsurface.modelelement3s = model->surfmesh.data_element3s;
8475         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8476         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8477         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8478         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8479         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8480         rsurface.modelsurfaces = model->data_surfaces;
8481         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8482         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8484         rsurface.modelgeneratedvertex = false;
8485         rsurface.batchgeneratedvertex = false;
8486         rsurface.batchfirstvertex = 0;
8487         rsurface.batchnumvertices = 0;
8488         rsurface.batchfirsttriangle = 0;
8489         rsurface.batchnumtriangles = 0;
8490         rsurface.batchvertex3f  = NULL;
8491         rsurface.batchvertex3f_vertexbuffer = NULL;
8492         rsurface.batchvertex3f_bufferoffset = 0;
8493         rsurface.batchsvector3f = NULL;
8494         rsurface.batchsvector3f_vertexbuffer = NULL;
8495         rsurface.batchsvector3f_bufferoffset = 0;
8496         rsurface.batchtvector3f = NULL;
8497         rsurface.batchtvector3f_vertexbuffer = NULL;
8498         rsurface.batchtvector3f_bufferoffset = 0;
8499         rsurface.batchnormal3f  = NULL;
8500         rsurface.batchnormal3f_vertexbuffer = NULL;
8501         rsurface.batchnormal3f_bufferoffset = 0;
8502         rsurface.batchlightmapcolor4f = NULL;
8503         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8504         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8505         rsurface.batchtexcoordtexture2f = NULL;
8506         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8507         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8508         rsurface.batchtexcoordlightmap2f = NULL;
8509         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8510         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8511         rsurface.batchskeletalindex4ub = NULL;
8512         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8513         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8514         rsurface.batchskeletalweight4ub = NULL;
8515         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8516         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8517         rsurface.batchvertexmesh = NULL;
8518         rsurface.batchvertexmesh_vertexbuffer = NULL;
8519         rsurface.batchvertexmesh_bufferoffset = 0;
8520         rsurface.batchelement3i = NULL;
8521         rsurface.batchelement3i_indexbuffer = NULL;
8522         rsurface.batchelement3i_bufferoffset = 0;
8523         rsurface.batchelement3s = NULL;
8524         rsurface.batchelement3s_indexbuffer = NULL;
8525         rsurface.batchelement3s_bufferoffset = 0;
8526         rsurface.passcolor4f = NULL;
8527         rsurface.passcolor4f_vertexbuffer = NULL;
8528         rsurface.passcolor4f_bufferoffset = 0;
8529         rsurface.forcecurrenttextureupdate = false;
8530 }
8531
8532 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8533 {
8534         dp_model_t *model = ent->model;
8535         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8536         //      return;
8537         rsurface.entity = (entity_render_t *)ent;
8538         rsurface.skeleton = ent->skeleton;
8539         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8540         rsurface.ent_skinnum = ent->skinnum;
8541         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;
8542         rsurface.ent_flags = ent->flags;
8543         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8544         rsurface.matrix = ent->matrix;
8545         rsurface.inversematrix = ent->inversematrix;
8546         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8547         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8548         R_EntityMatrix(&rsurface.matrix);
8549         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8550         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8551         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8552         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8553         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8554         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8555         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8556         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8557         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8558         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8559         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8560         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8561         rsurface.colormod[3] = ent->alpha;
8562         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8563         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8564         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8565         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8566         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8567         if (ent->model->brush.submodel && !prepass)
8568         {
8569                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8570                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8571         }
8572         // if the animcache code decided it should use the shader path, skip the deform step
8573         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8574         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8575         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8576         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8577         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8578         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8579         {
8580                 if (ent->animcache_vertex3f)
8581                 {
8582                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8583                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8584                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8585                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8586                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8587                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8588                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8589                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8590                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8591                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8592                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8593                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8594                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8595                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8596                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8597                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8598                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8599                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8600                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8601                 }
8602                 else if (wanttangents)
8603                 {
8604                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8605                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8606                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8607                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8608                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8609                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8610                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8611                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8612                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8613                         rsurface.modelvertexmesh = NULL;
8614                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8615                         rsurface.modelvertexmesh_bufferoffset = 0;
8616                         rsurface.modelvertex3f_vertexbuffer = NULL;
8617                         rsurface.modelvertex3f_bufferoffset = 0;
8618                         rsurface.modelvertex3f_vertexbuffer = 0;
8619                         rsurface.modelvertex3f_bufferoffset = 0;
8620                         rsurface.modelsvector3f_vertexbuffer = 0;
8621                         rsurface.modelsvector3f_bufferoffset = 0;
8622                         rsurface.modeltvector3f_vertexbuffer = 0;
8623                         rsurface.modeltvector3f_bufferoffset = 0;
8624                         rsurface.modelnormal3f_vertexbuffer = 0;
8625                         rsurface.modelnormal3f_bufferoffset = 0;
8626                 }
8627                 else if (wantnormals)
8628                 {
8629                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8630                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8631                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8632                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8633                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8634                         rsurface.modelsvector3f = NULL;
8635                         rsurface.modeltvector3f = NULL;
8636                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8637                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8638                         rsurface.modelvertexmesh = NULL;
8639                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8640                         rsurface.modelvertexmesh_bufferoffset = 0;
8641                         rsurface.modelvertex3f_vertexbuffer = NULL;
8642                         rsurface.modelvertex3f_bufferoffset = 0;
8643                         rsurface.modelvertex3f_vertexbuffer = 0;
8644                         rsurface.modelvertex3f_bufferoffset = 0;
8645                         rsurface.modelsvector3f_vertexbuffer = 0;
8646                         rsurface.modelsvector3f_bufferoffset = 0;
8647                         rsurface.modeltvector3f_vertexbuffer = 0;
8648                         rsurface.modeltvector3f_bufferoffset = 0;
8649                         rsurface.modelnormal3f_vertexbuffer = 0;
8650                         rsurface.modelnormal3f_bufferoffset = 0;
8651                 }
8652                 else
8653                 {
8654                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8655                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8656                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8657                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8658                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8659                         rsurface.modelsvector3f = NULL;
8660                         rsurface.modeltvector3f = NULL;
8661                         rsurface.modelnormal3f = NULL;
8662                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8663                         rsurface.modelvertexmesh = NULL;
8664                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8665                         rsurface.modelvertexmesh_bufferoffset = 0;
8666                         rsurface.modelvertex3f_vertexbuffer = NULL;
8667                         rsurface.modelvertex3f_bufferoffset = 0;
8668                         rsurface.modelvertex3f_vertexbuffer = 0;
8669                         rsurface.modelvertex3f_bufferoffset = 0;
8670                         rsurface.modelsvector3f_vertexbuffer = 0;
8671                         rsurface.modelsvector3f_bufferoffset = 0;
8672                         rsurface.modeltvector3f_vertexbuffer = 0;
8673                         rsurface.modeltvector3f_bufferoffset = 0;
8674                         rsurface.modelnormal3f_vertexbuffer = 0;
8675                         rsurface.modelnormal3f_bufferoffset = 0;
8676                 }
8677                 rsurface.modelgeneratedvertex = true;
8678         }
8679         else
8680         {
8681                 if (rsurface.entityskeletaltransform3x4)
8682                 {
8683                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8684                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8685                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8686                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8687                 }
8688                 else
8689                 {
8690                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8691                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8692                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8693                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8694                 }
8695                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8696                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8697                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8698                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8699                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8700                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8701                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8702                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8703                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8704                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8705                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8706                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8707                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8708                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8709                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8710                 rsurface.modelgeneratedvertex = false;
8711         }
8712         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8713         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8714         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8715         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8716         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8717         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8718         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8719         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8720         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8721         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8722         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8723         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8724         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8725         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8726         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8727         rsurface.modelelement3i = model->surfmesh.data_element3i;
8728         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8729         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8730         rsurface.modelelement3s = model->surfmesh.data_element3s;
8731         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8732         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8733         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8734         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8735         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8736         rsurface.modelsurfaces = model->data_surfaces;
8737         rsurface.batchgeneratedvertex = false;
8738         rsurface.batchfirstvertex = 0;
8739         rsurface.batchnumvertices = 0;
8740         rsurface.batchfirsttriangle = 0;
8741         rsurface.batchnumtriangles = 0;
8742         rsurface.batchvertex3f  = NULL;
8743         rsurface.batchvertex3f_vertexbuffer = NULL;
8744         rsurface.batchvertex3f_bufferoffset = 0;
8745         rsurface.batchsvector3f = NULL;
8746         rsurface.batchsvector3f_vertexbuffer = NULL;
8747         rsurface.batchsvector3f_bufferoffset = 0;
8748         rsurface.batchtvector3f = NULL;
8749         rsurface.batchtvector3f_vertexbuffer = NULL;
8750         rsurface.batchtvector3f_bufferoffset = 0;
8751         rsurface.batchnormal3f  = NULL;
8752         rsurface.batchnormal3f_vertexbuffer = NULL;
8753         rsurface.batchnormal3f_bufferoffset = 0;
8754         rsurface.batchlightmapcolor4f = NULL;
8755         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8756         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8757         rsurface.batchtexcoordtexture2f = NULL;
8758         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8759         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8760         rsurface.batchtexcoordlightmap2f = NULL;
8761         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8762         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8763         rsurface.batchskeletalindex4ub = NULL;
8764         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8765         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8766         rsurface.batchskeletalweight4ub = NULL;
8767         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8768         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8769         rsurface.batchvertexmesh = NULL;
8770         rsurface.batchvertexmesh_vertexbuffer = NULL;
8771         rsurface.batchvertexmesh_bufferoffset = 0;
8772         rsurface.batchelement3i = NULL;
8773         rsurface.batchelement3i_indexbuffer = NULL;
8774         rsurface.batchelement3i_bufferoffset = 0;
8775         rsurface.batchelement3s = NULL;
8776         rsurface.batchelement3s_indexbuffer = NULL;
8777         rsurface.batchelement3s_bufferoffset = 0;
8778         rsurface.passcolor4f = NULL;
8779         rsurface.passcolor4f_vertexbuffer = NULL;
8780         rsurface.passcolor4f_bufferoffset = 0;
8781         rsurface.forcecurrenttextureupdate = false;
8782 }
8783
8784 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)
8785 {
8786         rsurface.entity = r_refdef.scene.worldentity;
8787         rsurface.skeleton = NULL;
8788         rsurface.ent_skinnum = 0;
8789         rsurface.ent_qwskin = -1;
8790         rsurface.ent_flags = entflags;
8791         rsurface.shadertime = r_refdef.scene.time - shadertime;
8792         rsurface.modelnumvertices = numvertices;
8793         rsurface.modelnumtriangles = numtriangles;
8794         rsurface.matrix = *matrix;
8795         rsurface.inversematrix = *inversematrix;
8796         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8797         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8798         R_EntityMatrix(&rsurface.matrix);
8799         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8800         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8801         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8802         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8803         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8804         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8805         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8806         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8807         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8808         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8809         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8810         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8811         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);
8812         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8813         rsurface.frameblend[0].lerp = 1;
8814         rsurface.ent_alttextures = false;
8815         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8816         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8817         rsurface.entityskeletaltransform3x4 = NULL;
8818         rsurface.entityskeletaltransform3x4buffer = NULL;
8819         rsurface.entityskeletaltransform3x4offset = 0;
8820         rsurface.entityskeletaltransform3x4size = 0;
8821         rsurface.entityskeletalnumtransforms = 0;
8822         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8823         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8824         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8825         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8826         if (wanttangents)
8827         {
8828                 rsurface.modelvertex3f = (float *)vertex3f;
8829                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8830                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8831                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8832         }
8833         else if (wantnormals)
8834         {
8835                 rsurface.modelvertex3f = (float *)vertex3f;
8836                 rsurface.modelsvector3f = NULL;
8837                 rsurface.modeltvector3f = NULL;
8838                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8839         }
8840         else
8841         {
8842                 rsurface.modelvertex3f = (float *)vertex3f;
8843                 rsurface.modelsvector3f = NULL;
8844                 rsurface.modeltvector3f = NULL;
8845                 rsurface.modelnormal3f = NULL;
8846         }
8847         rsurface.modelvertexmesh = NULL;
8848         rsurface.modelvertexmesh_vertexbuffer = NULL;
8849         rsurface.modelvertexmesh_bufferoffset = 0;
8850         rsurface.modelvertex3f_vertexbuffer = 0;
8851         rsurface.modelvertex3f_bufferoffset = 0;
8852         rsurface.modelsvector3f_vertexbuffer = 0;
8853         rsurface.modelsvector3f_bufferoffset = 0;
8854         rsurface.modeltvector3f_vertexbuffer = 0;
8855         rsurface.modeltvector3f_bufferoffset = 0;
8856         rsurface.modelnormal3f_vertexbuffer = 0;
8857         rsurface.modelnormal3f_bufferoffset = 0;
8858         rsurface.modelgeneratedvertex = true;
8859         rsurface.modellightmapcolor4f  = (float *)color4f;
8860         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8861         rsurface.modellightmapcolor4f_bufferoffset = 0;
8862         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8863         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8864         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8865         rsurface.modeltexcoordlightmap2f  = NULL;
8866         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8867         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8868         rsurface.modelskeletalindex4ub = NULL;
8869         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8870         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8871         rsurface.modelskeletalweight4ub = NULL;
8872         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8873         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8874         rsurface.modelelement3i = (int *)element3i;
8875         rsurface.modelelement3i_indexbuffer = NULL;
8876         rsurface.modelelement3i_bufferoffset = 0;
8877         rsurface.modelelement3s = (unsigned short *)element3s;
8878         rsurface.modelelement3s_indexbuffer = NULL;
8879         rsurface.modelelement3s_bufferoffset = 0;
8880         rsurface.modellightmapoffsets = NULL;
8881         rsurface.modelsurfaces = NULL;
8882         rsurface.batchgeneratedvertex = false;
8883         rsurface.batchfirstvertex = 0;
8884         rsurface.batchnumvertices = 0;
8885         rsurface.batchfirsttriangle = 0;
8886         rsurface.batchnumtriangles = 0;
8887         rsurface.batchvertex3f  = NULL;
8888         rsurface.batchvertex3f_vertexbuffer = NULL;
8889         rsurface.batchvertex3f_bufferoffset = 0;
8890         rsurface.batchsvector3f = NULL;
8891         rsurface.batchsvector3f_vertexbuffer = NULL;
8892         rsurface.batchsvector3f_bufferoffset = 0;
8893         rsurface.batchtvector3f = NULL;
8894         rsurface.batchtvector3f_vertexbuffer = NULL;
8895         rsurface.batchtvector3f_bufferoffset = 0;
8896         rsurface.batchnormal3f  = NULL;
8897         rsurface.batchnormal3f_vertexbuffer = NULL;
8898         rsurface.batchnormal3f_bufferoffset = 0;
8899         rsurface.batchlightmapcolor4f = NULL;
8900         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8901         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8902         rsurface.batchtexcoordtexture2f = NULL;
8903         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8904         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8905         rsurface.batchtexcoordlightmap2f = NULL;
8906         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8907         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8908         rsurface.batchskeletalindex4ub = NULL;
8909         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8910         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8911         rsurface.batchskeletalweight4ub = NULL;
8912         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8913         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8914         rsurface.batchvertexmesh = NULL;
8915         rsurface.batchvertexmesh_vertexbuffer = NULL;
8916         rsurface.batchvertexmesh_bufferoffset = 0;
8917         rsurface.batchelement3i = NULL;
8918         rsurface.batchelement3i_indexbuffer = NULL;
8919         rsurface.batchelement3i_bufferoffset = 0;
8920         rsurface.batchelement3s = NULL;
8921         rsurface.batchelement3s_indexbuffer = NULL;
8922         rsurface.batchelement3s_bufferoffset = 0;
8923         rsurface.passcolor4f = NULL;
8924         rsurface.passcolor4f_vertexbuffer = NULL;
8925         rsurface.passcolor4f_bufferoffset = 0;
8926         rsurface.forcecurrenttextureupdate = true;
8927
8928         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8929         {
8930                 if ((wantnormals || wanttangents) && !normal3f)
8931                 {
8932                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8933                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8934                 }
8935                 if (wanttangents && !svector3f)
8936                 {
8937                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8938                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8939                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8940                 }
8941         }
8942 }
8943
8944 float RSurf_FogPoint(const float *v)
8945 {
8946         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8947         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8948         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8949         float FogHeightFade = r_refdef.fogheightfade;
8950         float fogfrac;
8951         unsigned int fogmasktableindex;
8952         if (r_refdef.fogplaneviewabove)
8953                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8954         else
8955                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8956         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8957         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8958 }
8959
8960 float RSurf_FogVertex(const float *v)
8961 {
8962         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8963         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8964         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8965         float FogHeightFade = rsurface.fogheightfade;
8966         float fogfrac;
8967         unsigned int fogmasktableindex;
8968         if (r_refdef.fogplaneviewabove)
8969                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8970         else
8971                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8972         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8973         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8974 }
8975
8976 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8977 {
8978         int i;
8979         for (i = 0;i < numelements;i++)
8980                 outelement3i[i] = inelement3i[i] + adjust;
8981 }
8982
8983 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8984 extern cvar_t gl_vbo;
8985 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8986 {
8987         int deformindex;
8988         int firsttriangle;
8989         int numtriangles;
8990         int firstvertex;
8991         int endvertex;
8992         int numvertices;
8993         int surfacefirsttriangle;
8994         int surfacenumtriangles;
8995         int surfacefirstvertex;
8996         int surfaceendvertex;
8997         int surfacenumvertices;
8998         int batchnumsurfaces = texturenumsurfaces;
8999         int batchnumvertices;
9000         int batchnumtriangles;
9001         int needsupdate;
9002         int i, j;
9003         qboolean gaps;
9004         qboolean dynamicvertex;
9005         float amplitude;
9006         float animpos;
9007         float scale;
9008         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9009         float waveparms[4];
9010         unsigned char *ub;
9011         q3shaderinfo_deform_t *deform;
9012         const msurface_t *surface, *firstsurface;
9013         r_vertexmesh_t *vertexmesh;
9014         if (!texturenumsurfaces)
9015                 return;
9016         // find vertex range of this surface batch
9017         gaps = false;
9018         firstsurface = texturesurfacelist[0];
9019         firsttriangle = firstsurface->num_firsttriangle;
9020         batchnumvertices = 0;
9021         batchnumtriangles = 0;
9022         firstvertex = endvertex = firstsurface->num_firstvertex;
9023         for (i = 0;i < texturenumsurfaces;i++)
9024         {
9025                 surface = texturesurfacelist[i];
9026                 if (surface != firstsurface + i)
9027                         gaps = true;
9028                 surfacefirstvertex = surface->num_firstvertex;
9029                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9030                 surfacenumvertices = surface->num_vertices;
9031                 surfacenumtriangles = surface->num_triangles;
9032                 if (firstvertex > surfacefirstvertex)
9033                         firstvertex = surfacefirstvertex;
9034                 if (endvertex < surfaceendvertex)
9035                         endvertex = surfaceendvertex;
9036                 batchnumvertices += surfacenumvertices;
9037                 batchnumtriangles += surfacenumtriangles;
9038         }
9039
9040         r_refdef.stats[r_stat_batch_batches]++;
9041         if (gaps)
9042                 r_refdef.stats[r_stat_batch_withgaps]++;
9043         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9044         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9045         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9046
9047         // we now know the vertex range used, and if there are any gaps in it
9048         rsurface.batchfirstvertex = firstvertex;
9049         rsurface.batchnumvertices = endvertex - firstvertex;
9050         rsurface.batchfirsttriangle = firsttriangle;
9051         rsurface.batchnumtriangles = batchnumtriangles;
9052
9053         // this variable holds flags for which properties have been updated that
9054         // may require regenerating vertexmesh array...
9055         needsupdate = 0;
9056
9057         // check if any dynamic vertex processing must occur
9058         dynamicvertex = false;
9059
9060         // a cvar to force the dynamic vertex path to be taken, for debugging
9061         if (r_batch_debugdynamicvertexpath.integer)
9062         {
9063                 if (!dynamicvertex)
9064                 {
9065                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9066                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9067                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9068                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9069                 }
9070                 dynamicvertex = true;
9071         }
9072
9073         // if there is a chance of animated vertex colors, it's a dynamic batch
9074         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9075         {
9076                 if (!dynamicvertex)
9077                 {
9078                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9079                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9080                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9081                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9082                 }
9083                 dynamicvertex = true;
9084                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9085         }
9086
9087         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9088         {
9089                 switch (deform->deform)
9090                 {
9091                 default:
9092                 case Q3DEFORM_PROJECTIONSHADOW:
9093                 case Q3DEFORM_TEXT0:
9094                 case Q3DEFORM_TEXT1:
9095                 case Q3DEFORM_TEXT2:
9096                 case Q3DEFORM_TEXT3:
9097                 case Q3DEFORM_TEXT4:
9098                 case Q3DEFORM_TEXT5:
9099                 case Q3DEFORM_TEXT6:
9100                 case Q3DEFORM_TEXT7:
9101                 case Q3DEFORM_NONE:
9102                         break;
9103                 case Q3DEFORM_AUTOSPRITE:
9104                         if (!dynamicvertex)
9105                         {
9106                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9107                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9108                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9109                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9110                         }
9111                         dynamicvertex = true;
9112                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9113                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9114                         break;
9115                 case Q3DEFORM_AUTOSPRITE2:
9116                         if (!dynamicvertex)
9117                         {
9118                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9119                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9120                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9121                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9122                         }
9123                         dynamicvertex = true;
9124                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9125                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9126                         break;
9127                 case Q3DEFORM_NORMAL:
9128                         if (!dynamicvertex)
9129                         {
9130                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9131                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9132                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9133                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9134                         }
9135                         dynamicvertex = true;
9136                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9137                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9138                         break;
9139                 case Q3DEFORM_WAVE:
9140                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9141                                 break; // if wavefunc is a nop, ignore this transform
9142                         if (!dynamicvertex)
9143                         {
9144                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9145                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9146                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9147                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9148                         }
9149                         dynamicvertex = true;
9150                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9151                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9152                         break;
9153                 case Q3DEFORM_BULGE:
9154                         if (!dynamicvertex)
9155                         {
9156                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9157                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9158                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9159                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9160                         }
9161                         dynamicvertex = true;
9162                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9163                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9164                         break;
9165                 case Q3DEFORM_MOVE:
9166                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9167                                 break; // if wavefunc is a nop, ignore this transform
9168                         if (!dynamicvertex)
9169                         {
9170                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9171                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9172                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9173                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9174                         }
9175                         dynamicvertex = true;
9176                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9177                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9178                         break;
9179                 }
9180         }
9181         switch(rsurface.texture->tcgen.tcgen)
9182         {
9183         default:
9184         case Q3TCGEN_TEXTURE:
9185                 break;
9186         case Q3TCGEN_LIGHTMAP:
9187                 if (!dynamicvertex)
9188                 {
9189                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9190                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9191                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9192                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9193                 }
9194                 dynamicvertex = true;
9195                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9196                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9197                 break;
9198         case Q3TCGEN_VECTOR:
9199                 if (!dynamicvertex)
9200                 {
9201                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9202                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9203                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9204                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9205                 }
9206                 dynamicvertex = true;
9207                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9208                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9209                 break;
9210         case Q3TCGEN_ENVIRONMENT:
9211                 if (!dynamicvertex)
9212                 {
9213                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9214                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9215                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9216                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9217                 }
9218                 dynamicvertex = true;
9219                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9220                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9221                 break;
9222         }
9223         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9224         {
9225                 if (!dynamicvertex)
9226                 {
9227                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9228                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9229                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9230                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9231                 }
9232                 dynamicvertex = true;
9233                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9234                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9235         }
9236
9237         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9238         {
9239                 if (!dynamicvertex)
9240                 {
9241                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9242                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9243                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9244                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9245                 }
9246                 dynamicvertex = true;
9247                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9248         }
9249
9250         // when the model data has no vertex buffer (dynamic mesh), we need to
9251         // eliminate gaps
9252         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9253                 batchneed |= BATCHNEED_NOGAPS;
9254
9255         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9256         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9257         // we ensure this by treating the vertex batch as dynamic...
9258         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9259         {
9260                 if (!dynamicvertex)
9261                 {
9262                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9263                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9264                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9265                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9266                 }
9267                 dynamicvertex = true;
9268         }
9269
9270         if (dynamicvertex)
9271         {
9272                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9273                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9274                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9275                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9276                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9277                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9278                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9279                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9280         }
9281
9282         // if needsupdate, we have to do a dynamic vertex batch for sure
9283         if (needsupdate & batchneed)
9284         {
9285                 if (!dynamicvertex)
9286                 {
9287                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9288                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9289                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9290                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9291                 }
9292                 dynamicvertex = true;
9293         }
9294
9295         // see if we need to build vertexmesh from arrays
9296         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9297         {
9298                 if (!dynamicvertex)
9299                 {
9300                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9301                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9302                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9303                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9304                 }
9305                 dynamicvertex = true;
9306         }
9307
9308         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9309         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9310                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9311
9312         rsurface.batchvertex3f = rsurface.modelvertex3f;
9313         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9314         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9315         rsurface.batchsvector3f = rsurface.modelsvector3f;
9316         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9317         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9318         rsurface.batchtvector3f = rsurface.modeltvector3f;
9319         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9320         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9321         rsurface.batchnormal3f = rsurface.modelnormal3f;
9322         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9323         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9324         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9325         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9326         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9327         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9328         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9329         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9330         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9331         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9332         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9333         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9334         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9335         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9336         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9337         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9338         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9339         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9340         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9341         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9342         rsurface.batchelement3i = rsurface.modelelement3i;
9343         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9344         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9345         rsurface.batchelement3s = rsurface.modelelement3s;
9346         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9347         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9348         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9349         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9350         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9351         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9352         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9353
9354         // if any dynamic vertex processing has to occur in software, we copy the
9355         // entire surface list together before processing to rebase the vertices
9356         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9357         //
9358         // if any gaps exist and we do not have a static vertex buffer, we have to
9359         // copy the surface list together to avoid wasting upload bandwidth on the
9360         // vertices in the gaps.
9361         //
9362         // if gaps exist and we have a static vertex buffer, we can choose whether
9363         // to combine the index buffer ranges into one dynamic index buffer or
9364         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9365         //
9366         // in many cases the batch is reduced to one draw call.
9367
9368         rsurface.batchmultidraw = false;
9369         rsurface.batchmultidrawnumsurfaces = 0;
9370         rsurface.batchmultidrawsurfacelist = NULL;
9371
9372         if (!dynamicvertex)
9373         {
9374                 // static vertex data, just set pointers...
9375                 rsurface.batchgeneratedvertex = false;
9376                 // if there are gaps, we want to build a combined index buffer,
9377                 // otherwise use the original static buffer with an appropriate offset
9378                 if (gaps)
9379                 {
9380                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9381                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9382                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9383                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9384                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9385                         {
9386                                 rsurface.batchmultidraw = true;
9387                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9388                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9389                                 return;
9390                         }
9391                         // build a new triangle elements array for this batch
9392                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9393                         rsurface.batchfirsttriangle = 0;
9394                         numtriangles = 0;
9395                         for (i = 0;i < texturenumsurfaces;i++)
9396                         {
9397                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9398                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9399                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9400                                 numtriangles += surfacenumtriangles;
9401                         }
9402                         rsurface.batchelement3i_indexbuffer = NULL;
9403                         rsurface.batchelement3i_bufferoffset = 0;
9404                         rsurface.batchelement3s = NULL;
9405                         rsurface.batchelement3s_indexbuffer = NULL;
9406                         rsurface.batchelement3s_bufferoffset = 0;
9407                         if (endvertex <= 65536)
9408                         {
9409                                 // make a 16bit (unsigned short) index array if possible
9410                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9411                                 for (i = 0;i < numtriangles*3;i++)
9412                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9413                         }
9414                         // upload buffer data for the copytriangles batch
9415                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9416                         {
9417                                 if (rsurface.batchelement3s)
9418                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9419                                 else if (rsurface.batchelement3i)
9420                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9421                         }
9422                 }
9423                 else
9424                 {
9425                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9426                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9427                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9428                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9429                 }
9430                 return;
9431         }
9432
9433         // something needs software processing, do it for real...
9434         // we only directly handle separate array data in this case and then
9435         // generate interleaved data if needed...
9436         rsurface.batchgeneratedvertex = true;
9437         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9438         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9439         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9440         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9441
9442         // now copy the vertex data into a combined array and make an index array
9443         // (this is what Quake3 does all the time)
9444         // we also apply any skeletal animation here that would have been done in
9445         // the vertex shader, because most of the dynamic vertex animation cases
9446         // need actual vertex positions and normals
9447         //if (dynamicvertex)
9448         {
9449                 rsurface.batchvertexmesh = NULL;
9450                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9451                 rsurface.batchvertexmesh_bufferoffset = 0;
9452                 rsurface.batchvertex3f = NULL;
9453                 rsurface.batchvertex3f_vertexbuffer = NULL;
9454                 rsurface.batchvertex3f_bufferoffset = 0;
9455                 rsurface.batchsvector3f = NULL;
9456                 rsurface.batchsvector3f_vertexbuffer = NULL;
9457                 rsurface.batchsvector3f_bufferoffset = 0;
9458                 rsurface.batchtvector3f = NULL;
9459                 rsurface.batchtvector3f_vertexbuffer = NULL;
9460                 rsurface.batchtvector3f_bufferoffset = 0;
9461                 rsurface.batchnormal3f = NULL;
9462                 rsurface.batchnormal3f_vertexbuffer = NULL;
9463                 rsurface.batchnormal3f_bufferoffset = 0;
9464                 rsurface.batchlightmapcolor4f = NULL;
9465                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9466                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9467                 rsurface.batchtexcoordtexture2f = NULL;
9468                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9469                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9470                 rsurface.batchtexcoordlightmap2f = NULL;
9471                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9472                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9473                 rsurface.batchskeletalindex4ub = NULL;
9474                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9475                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9476                 rsurface.batchskeletalweight4ub = NULL;
9477                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9478                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9479                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9480                 rsurface.batchelement3i_indexbuffer = NULL;
9481                 rsurface.batchelement3i_bufferoffset = 0;
9482                 rsurface.batchelement3s = NULL;
9483                 rsurface.batchelement3s_indexbuffer = NULL;
9484                 rsurface.batchelement3s_bufferoffset = 0;
9485                 rsurface.batchskeletaltransform3x4buffer = NULL;
9486                 rsurface.batchskeletaltransform3x4offset = 0;
9487                 rsurface.batchskeletaltransform3x4size = 0;
9488                 // we'll only be setting up certain arrays as needed
9489                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9490                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9491                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9492                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9493                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9494                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9495                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9496                 {
9497                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9498                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9499                 }
9500                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9501                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9502                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9503                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9504                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9505                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9506                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9507                 {
9508                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9509                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9510                 }
9511                 numvertices = 0;
9512                 numtriangles = 0;
9513                 for (i = 0;i < texturenumsurfaces;i++)
9514                 {
9515                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9516                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9517                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9518                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9519                         // copy only the data requested
9520                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9521                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9522                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9523                         {
9524                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9525                                 {
9526                                         if (rsurface.batchvertex3f)
9527                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9528                                         else
9529                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9530                                 }
9531                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9532                                 {
9533                                         if (rsurface.modelnormal3f)
9534                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9535                                         else
9536                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9537                                 }
9538                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9539                                 {
9540                                         if (rsurface.modelsvector3f)
9541                                         {
9542                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9543                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9544                                         }
9545                                         else
9546                                         {
9547                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9548                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9549                                         }
9550                                 }
9551                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9552                                 {
9553                                         if (rsurface.modellightmapcolor4f)
9554                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9555                                         else
9556                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9557                                 }
9558                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9559                                 {
9560                                         if (rsurface.modeltexcoordtexture2f)
9561                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9562                                         else
9563                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9564                                 }
9565                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9566                                 {
9567                                         if (rsurface.modeltexcoordlightmap2f)
9568                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9569                                         else
9570                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9571                                 }
9572                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9573                                 {
9574                                         if (rsurface.modelskeletalindex4ub)
9575                                         {
9576                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9577                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9578                                         }
9579                                         else
9580                                         {
9581                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9582                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9583                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9584                                                 for (j = 0;j < surfacenumvertices;j++)
9585                                                         ub[j*4] = 255;
9586                                         }
9587                                 }
9588                         }
9589                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9590                         numvertices += surfacenumvertices;
9591                         numtriangles += surfacenumtriangles;
9592                 }
9593
9594                 // generate a 16bit index array as well if possible
9595                 // (in general, dynamic batches fit)
9596                 if (numvertices <= 65536)
9597                 {
9598                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9599                         for (i = 0;i < numtriangles*3;i++)
9600                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9601                 }
9602
9603                 // since we've copied everything, the batch now starts at 0
9604                 rsurface.batchfirstvertex = 0;
9605                 rsurface.batchnumvertices = batchnumvertices;
9606                 rsurface.batchfirsttriangle = 0;
9607                 rsurface.batchnumtriangles = batchnumtriangles;
9608         }
9609
9610         // apply skeletal animation that would have been done in the vertex shader
9611         if (rsurface.batchskeletaltransform3x4)
9612         {
9613                 const unsigned char *si;
9614                 const unsigned char *sw;
9615                 const float *t[4];
9616                 const float *b = rsurface.batchskeletaltransform3x4;
9617                 float *vp, *vs, *vt, *vn;
9618                 float w[4];
9619                 float m[3][4], n[3][4];
9620                 float tp[3], ts[3], tt[3], tn[3];
9621                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9622                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9623                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9624                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9625                 si = rsurface.batchskeletalindex4ub;
9626                 sw = rsurface.batchskeletalweight4ub;
9627                 vp = rsurface.batchvertex3f;
9628                 vs = rsurface.batchsvector3f;
9629                 vt = rsurface.batchtvector3f;
9630                 vn = rsurface.batchnormal3f;
9631                 memset(m[0], 0, sizeof(m));
9632                 memset(n[0], 0, sizeof(n));
9633                 for (i = 0;i < batchnumvertices;i++)
9634                 {
9635                         t[0] = b + si[0]*12;
9636                         if (sw[0] == 255)
9637                         {
9638                                 // common case - only one matrix
9639                                 m[0][0] = t[0][ 0];
9640                                 m[0][1] = t[0][ 1];
9641                                 m[0][2] = t[0][ 2];
9642                                 m[0][3] = t[0][ 3];
9643                                 m[1][0] = t[0][ 4];
9644                                 m[1][1] = t[0][ 5];
9645                                 m[1][2] = t[0][ 6];
9646                                 m[1][3] = t[0][ 7];
9647                                 m[2][0] = t[0][ 8];
9648                                 m[2][1] = t[0][ 9];
9649                                 m[2][2] = t[0][10];
9650                                 m[2][3] = t[0][11];
9651                         }
9652                         else if (sw[2] + sw[3])
9653                         {
9654                                 // blend 4 matrices
9655                                 t[1] = b + si[1]*12;
9656                                 t[2] = b + si[2]*12;
9657                                 t[3] = b + si[3]*12;
9658                                 w[0] = sw[0] * (1.0f / 255.0f);
9659                                 w[1] = sw[1] * (1.0f / 255.0f);
9660                                 w[2] = sw[2] * (1.0f / 255.0f);
9661                                 w[3] = sw[3] * (1.0f / 255.0f);
9662                                 // blend the matrices
9663                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9664                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9665                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9666                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9667                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9668                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9669                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9670                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9671                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9672                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9673                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9674                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9675                         }
9676                         else
9677                         {
9678                                 // blend 2 matrices
9679                                 t[1] = b + si[1]*12;
9680                                 w[0] = sw[0] * (1.0f / 255.0f);
9681                                 w[1] = sw[1] * (1.0f / 255.0f);
9682                                 // blend the matrices
9683                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9684                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9685                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9686                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9687                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9688                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9689                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9690                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9691                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9692                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9693                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9694                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9695                         }
9696                         si += 4;
9697                         sw += 4;
9698                         // modify the vertex
9699                         VectorCopy(vp, tp);
9700                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9701                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9702                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9703                         vp += 3;
9704                         if (vn)
9705                         {
9706                                 // the normal transformation matrix is a set of cross products...
9707                                 CrossProduct(m[1], m[2], n[0]);
9708                                 CrossProduct(m[2], m[0], n[1]);
9709                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9710                                 VectorCopy(vn, tn);
9711                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9712                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9713                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9714                                 VectorNormalize(vn);
9715                                 vn += 3;
9716                                 if (vs)
9717                                 {
9718                                         VectorCopy(vs, ts);
9719                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9720                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9721                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9722                                         VectorNormalize(vs);
9723                                         vs += 3;
9724                                         VectorCopy(vt, tt);
9725                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9726                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9727                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9728                                         VectorNormalize(vt);
9729                                         vt += 3;
9730                                 }
9731                         }
9732                 }
9733                 rsurface.batchskeletaltransform3x4 = NULL;
9734                 rsurface.batchskeletalnumtransforms = 0;
9735         }
9736
9737         // q1bsp surfaces rendered in vertex color mode have to have colors
9738         // calculated based on lightstyles
9739         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9740         {
9741                 // generate color arrays for the surfaces in this list
9742                 int c[4];
9743                 int scale;
9744                 int size3;
9745                 const int *offsets;
9746                 const unsigned char *lm;
9747                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9748                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9749                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9750                 numvertices = 0;
9751                 for (i = 0;i < texturenumsurfaces;i++)
9752                 {
9753                         surface = texturesurfacelist[i];
9754                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9755                         surfacenumvertices = surface->num_vertices;
9756                         if (surface->lightmapinfo->samples)
9757                         {
9758                                 for (j = 0;j < surfacenumvertices;j++)
9759                                 {
9760                                         lm = surface->lightmapinfo->samples + offsets[j];
9761                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9762                                         VectorScale(lm, scale, c);
9763                                         if (surface->lightmapinfo->styles[1] != 255)
9764                                         {
9765                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9766                                                 lm += size3;
9767                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9768                                                 VectorMA(c, scale, lm, c);
9769                                                 if (surface->lightmapinfo->styles[2] != 255)
9770                                                 {
9771                                                         lm += size3;
9772                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9773                                                         VectorMA(c, scale, lm, c);
9774                                                         if (surface->lightmapinfo->styles[3] != 255)
9775                                                         {
9776                                                                 lm += size3;
9777                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9778                                                                 VectorMA(c, scale, lm, c);
9779                                                         }
9780                                                 }
9781                                         }
9782                                         c[0] >>= 7;
9783                                         c[1] >>= 7;
9784                                         c[2] >>= 7;
9785                                         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);
9786                                         numvertices++;
9787                                 }
9788                         }
9789                         else
9790                         {
9791                                 for (j = 0;j < surfacenumvertices;j++)
9792                                 {
9793                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9794                                         numvertices++;
9795                                 }
9796                         }
9797                 }
9798         }
9799
9800         // if vertices are deformed (sprite flares and things in maps, possibly
9801         // water waves, bulges and other deformations), modify the copied vertices
9802         // in place
9803         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9804         {
9805                 switch (deform->deform)
9806                 {
9807                 default:
9808                 case Q3DEFORM_PROJECTIONSHADOW:
9809                 case Q3DEFORM_TEXT0:
9810                 case Q3DEFORM_TEXT1:
9811                 case Q3DEFORM_TEXT2:
9812                 case Q3DEFORM_TEXT3:
9813                 case Q3DEFORM_TEXT4:
9814                 case Q3DEFORM_TEXT5:
9815                 case Q3DEFORM_TEXT6:
9816                 case Q3DEFORM_TEXT7:
9817                 case Q3DEFORM_NONE:
9818                         break;
9819                 case Q3DEFORM_AUTOSPRITE:
9820                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9821                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9822                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9823                         VectorNormalize(newforward);
9824                         VectorNormalize(newright);
9825                         VectorNormalize(newup);
9826 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9827 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9828 //                      rsurface.batchvertex3f_bufferoffset = 0;
9829 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9830 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9831 //                      rsurface.batchsvector3f_bufferoffset = 0;
9832 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9833 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9834 //                      rsurface.batchtvector3f_bufferoffset = 0;
9835 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9836 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9837 //                      rsurface.batchnormal3f_bufferoffset = 0;
9838                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9839                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9840                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9841                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9842                                 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);
9843                         // a single autosprite surface can contain multiple sprites...
9844                         for (j = 0;j < batchnumvertices - 3;j += 4)
9845                         {
9846                                 VectorClear(center);
9847                                 for (i = 0;i < 4;i++)
9848                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9849                                 VectorScale(center, 0.25f, center);
9850                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9851                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9852                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9853                                 for (i = 0;i < 4;i++)
9854                                 {
9855                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9856                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9857                                 }
9858                         }
9859                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9860                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9861                         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);
9862                         break;
9863                 case Q3DEFORM_AUTOSPRITE2:
9864                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9865                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9866                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9867                         VectorNormalize(newforward);
9868                         VectorNormalize(newright);
9869                         VectorNormalize(newup);
9870 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9871 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9872 //                      rsurface.batchvertex3f_bufferoffset = 0;
9873                         {
9874                                 const float *v1, *v2;
9875                                 vec3_t start, end;
9876                                 float f, l;
9877                                 struct
9878                                 {
9879                                         float length2;
9880                                         const float *v1;
9881                                         const float *v2;
9882                                 }
9883                                 shortest[2];
9884                                 memset(shortest, 0, sizeof(shortest));
9885                                 // a single autosprite surface can contain multiple sprites...
9886                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9887                                 {
9888                                         VectorClear(center);
9889                                         for (i = 0;i < 4;i++)
9890                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9891                                         VectorScale(center, 0.25f, center);
9892                                         // find the two shortest edges, then use them to define the
9893                                         // axis vectors for rotating around the central axis
9894                                         for (i = 0;i < 6;i++)
9895                                         {
9896                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9897                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9898                                                 l = VectorDistance2(v1, v2);
9899                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9900                                                 if (v1[2] != v2[2])
9901                                                         l += (1.0f / 1024.0f);
9902                                                 if (shortest[0].length2 > l || i == 0)
9903                                                 {
9904                                                         shortest[1] = shortest[0];
9905                                                         shortest[0].length2 = l;
9906                                                         shortest[0].v1 = v1;
9907                                                         shortest[0].v2 = v2;
9908                                                 }
9909                                                 else if (shortest[1].length2 > l || i == 1)
9910                                                 {
9911                                                         shortest[1].length2 = l;
9912                                                         shortest[1].v1 = v1;
9913                                                         shortest[1].v2 = v2;
9914                                                 }
9915                                         }
9916                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9917                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9918                                         // this calculates the right vector from the shortest edge
9919                                         // and the up vector from the edge midpoints
9920                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9921                                         VectorNormalize(right);
9922                                         VectorSubtract(end, start, up);
9923                                         VectorNormalize(up);
9924                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9925                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9926                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9927                                         VectorNegate(forward, forward);
9928                                         VectorReflect(forward, 0, up, forward);
9929                                         VectorNormalize(forward);
9930                                         CrossProduct(up, forward, newright);
9931                                         VectorNormalize(newright);
9932                                         // rotate the quad around the up axis vector, this is made
9933                                         // especially easy by the fact we know the quad is flat,
9934                                         // so we only have to subtract the center position and
9935                                         // measure distance along the right vector, and then
9936                                         // multiply that by the newright vector and add back the
9937                                         // center position
9938                                         // we also need to subtract the old position to undo the
9939                                         // displacement from the center, which we do with a
9940                                         // DotProduct, the subtraction/addition of center is also
9941                                         // optimized into DotProducts here
9942                                         l = DotProduct(right, center);
9943                                         for (i = 0;i < 4;i++)
9944                                         {
9945                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9946                                                 f = DotProduct(right, v1) - l;
9947                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9948                                         }
9949                                 }
9950                         }
9951                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9952                         {
9953 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9954 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9955 //                              rsurface.batchnormal3f_bufferoffset = 0;
9956                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9957                         }
9958                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9959                         {
9960 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9961 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9962 //                              rsurface.batchsvector3f_bufferoffset = 0;
9963 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9964 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9965 //                              rsurface.batchtvector3f_bufferoffset = 0;
9966                                 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);
9967                         }
9968                         break;
9969                 case Q3DEFORM_NORMAL:
9970                         // deform the normals to make reflections wavey
9971                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9972                         rsurface.batchnormal3f_vertexbuffer = NULL;
9973                         rsurface.batchnormal3f_bufferoffset = 0;
9974                         for (j = 0;j < batchnumvertices;j++)
9975                         {
9976                                 float vertex[3];
9977                                 float *normal = rsurface.batchnormal3f + 3*j;
9978                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9979                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9980                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9981                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9982                                 VectorNormalize(normal);
9983                         }
9984                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9985                         {
9986 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9987 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9988 //                              rsurface.batchsvector3f_bufferoffset = 0;
9989 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9990 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9991 //                              rsurface.batchtvector3f_bufferoffset = 0;
9992                                 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);
9993                         }
9994                         break;
9995                 case Q3DEFORM_WAVE:
9996                         // deform vertex array to make wavey water and flags and such
9997                         waveparms[0] = deform->waveparms[0];
9998                         waveparms[1] = deform->waveparms[1];
9999                         waveparms[2] = deform->waveparms[2];
10000                         waveparms[3] = deform->waveparms[3];
10001                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10002                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10003                         // this is how a divisor of vertex influence on deformation
10004                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10005                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10006 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10007 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10008 //                      rsurface.batchvertex3f_bufferoffset = 0;
10009 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10010 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10011 //                      rsurface.batchnormal3f_bufferoffset = 0;
10012                         for (j = 0;j < batchnumvertices;j++)
10013                         {
10014                                 // if the wavefunc depends on time, evaluate it per-vertex
10015                                 if (waveparms[3])
10016                                 {
10017                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10018                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10019                                 }
10020                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10021                         }
10022                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10023                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10024                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10025                         {
10026 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10027 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10028 //                              rsurface.batchsvector3f_bufferoffset = 0;
10029 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10030 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10031 //                              rsurface.batchtvector3f_bufferoffset = 0;
10032                                 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);
10033                         }
10034                         break;
10035                 case Q3DEFORM_BULGE:
10036                         // deform vertex array to make the surface have moving bulges
10037 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10038 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10039 //                      rsurface.batchvertex3f_bufferoffset = 0;
10040 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10041 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10042 //                      rsurface.batchnormal3f_bufferoffset = 0;
10043                         for (j = 0;j < batchnumvertices;j++)
10044                         {
10045                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10046                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10047                         }
10048                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10049                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10050                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10051                         {
10052 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10053 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10054 //                              rsurface.batchsvector3f_bufferoffset = 0;
10055 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10056 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10057 //                              rsurface.batchtvector3f_bufferoffset = 0;
10058                                 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);
10059                         }
10060                         break;
10061                 case Q3DEFORM_MOVE:
10062                         // deform vertex array
10063                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10064                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10065                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10066                         VectorScale(deform->parms, scale, waveparms);
10067 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10068 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10069 //                      rsurface.batchvertex3f_bufferoffset = 0;
10070                         for (j = 0;j < batchnumvertices;j++)
10071                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10072                         break;
10073                 }
10074         }
10075
10076         // generate texcoords based on the chosen texcoord source
10077         switch(rsurface.texture->tcgen.tcgen)
10078         {
10079         default:
10080         case Q3TCGEN_TEXTURE:
10081                 break;
10082         case Q3TCGEN_LIGHTMAP:
10083 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10084 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10085 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10086                 if (rsurface.batchtexcoordlightmap2f)
10087                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10088                 break;
10089         case Q3TCGEN_VECTOR:
10090 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10091 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10092 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10093                 for (j = 0;j < batchnumvertices;j++)
10094                 {
10095                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10096                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10097                 }
10098                 break;
10099         case Q3TCGEN_ENVIRONMENT:
10100                 // make environment reflections using a spheremap
10101                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10102                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10103                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10104                 for (j = 0;j < batchnumvertices;j++)
10105                 {
10106                         // identical to Q3A's method, but executed in worldspace so
10107                         // carried models can be shiny too
10108
10109                         float viewer[3], d, reflected[3], worldreflected[3];
10110
10111                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10112                         // VectorNormalize(viewer);
10113
10114                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10115
10116                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10117                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10118                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10119                         // note: this is proportinal to viewer, so we can normalize later
10120
10121                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10122                         VectorNormalize(worldreflected);
10123
10124                         // note: this sphere map only uses world x and z!
10125                         // so positive and negative y will LOOK THE SAME.
10126                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10127                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10128                 }
10129                 break;
10130         }
10131         // the only tcmod that needs software vertex processing is turbulent, so
10132         // check for it here and apply the changes if needed
10133         // and we only support that as the first one
10134         // (handling a mixture of turbulent and other tcmods would be problematic
10135         //  without punting it entirely to a software path)
10136         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10137         {
10138                 amplitude = rsurface.texture->tcmods[0].parms[1];
10139                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10140 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10141 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10142 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10143                 for (j = 0;j < batchnumvertices;j++)
10144                 {
10145                         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);
10146                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10147                 }
10148         }
10149
10150         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10151         {
10152                 // convert the modified arrays to vertex structs
10153 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10154 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10155 //              rsurface.batchvertexmesh_bufferoffset = 0;
10156                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10157                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10158                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10159                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10160                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10161                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10162                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10163                 {
10164                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10165                         {
10166                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10167                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10168                         }
10169                 }
10170                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10171                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10172                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10173                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10174                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10175                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10176                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10177                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10178                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10179                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10180                 {
10181                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10182                         {
10183                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10184                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10185                         }
10186                 }
10187         }
10188
10189         // upload buffer data for the dynamic batch
10190         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10191         {
10192                 if (rsurface.batchvertexmesh)
10193                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10194                 else
10195                 {
10196                         if (rsurface.batchvertex3f)
10197                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10198                         if (rsurface.batchsvector3f)
10199                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10200                         if (rsurface.batchtvector3f)
10201                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10202                         if (rsurface.batchnormal3f)
10203                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10204                         if (rsurface.batchlightmapcolor4f)
10205                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10206                         if (rsurface.batchtexcoordtexture2f)
10207                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10208                         if (rsurface.batchtexcoordlightmap2f)
10209                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10210                         if (rsurface.batchskeletalindex4ub)
10211                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10212                         if (rsurface.batchskeletalweight4ub)
10213                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10214                 }
10215                 if (rsurface.batchelement3s)
10216                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10217                 else if (rsurface.batchelement3i)
10218                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10219         }
10220 }
10221
10222 void RSurf_DrawBatch(void)
10223 {
10224         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10225         // through the pipeline, killing it earlier in the pipeline would have
10226         // per-surface overhead rather than per-batch overhead, so it's best to
10227         // reject it here, before it hits glDraw.
10228         if (rsurface.batchnumtriangles == 0)
10229                 return;
10230 #if 0
10231         // batch debugging code
10232         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10233         {
10234                 int i;
10235                 int j;
10236                 int c;
10237                 const int *e;
10238                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10239                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10240                 {
10241                         c = e[i];
10242                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10243                         {
10244                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10245                                 {
10246                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10247                                                 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);
10248                                         break;
10249                                 }
10250                         }
10251                 }
10252         }
10253 #endif
10254         if (rsurface.batchmultidraw)
10255         {
10256                 // issue multiple draws rather than copying index data
10257                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10258                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10259                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10260                 for (i = 0;i < numsurfaces;)
10261                 {
10262                         // combine consecutive surfaces as one draw
10263                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10264                                 if (surfacelist[j] != surfacelist[k] + 1)
10265                                         break;
10266                         firstvertex = surfacelist[i]->num_firstvertex;
10267                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10268                         firsttriangle = surfacelist[i]->num_firsttriangle;
10269                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10270                         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);
10271                         i = j;
10272                 }
10273         }
10274         else
10275         {
10276                 // there is only one consecutive run of index data (may have been combined)
10277                 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);
10278         }
10279 }
10280
10281 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10282 {
10283         // pick the closest matching water plane
10284         int planeindex, vertexindex, bestplaneindex = -1;
10285         float d, bestd;
10286         vec3_t vert;
10287         const float *v;
10288         r_waterstate_waterplane_t *p;
10289         qboolean prepared = false;
10290         bestd = 0;
10291         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10292         {
10293                 if(p->camera_entity != rsurface.texture->camera_entity)
10294                         continue;
10295                 d = 0;
10296                 if(!prepared)
10297                 {
10298                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10299                         prepared = true;
10300                         if(rsurface.batchnumvertices == 0)
10301                                 break;
10302                 }
10303                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10304                 {
10305                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10306                         d += fabs(PlaneDiff(vert, &p->plane));
10307                 }
10308                 if (bestd > d || bestplaneindex < 0)
10309                 {
10310                         bestd = d;
10311                         bestplaneindex = planeindex;
10312                 }
10313         }
10314         return bestplaneindex;
10315         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10316         // this situation though, as it might be better to render single larger
10317         // batches with useless stuff (backface culled for example) than to
10318         // render multiple smaller batches
10319 }
10320
10321 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10322 {
10323         int i;
10324         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10325         rsurface.passcolor4f_vertexbuffer = 0;
10326         rsurface.passcolor4f_bufferoffset = 0;
10327         for (i = 0;i < rsurface.batchnumvertices;i++)
10328                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10329 }
10330
10331 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10332 {
10333         int i;
10334         float f;
10335         const float *v;
10336         const float *c;
10337         float *c2;
10338         if (rsurface.passcolor4f)
10339         {
10340                 // generate color arrays
10341                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10342                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10343                 rsurface.passcolor4f_vertexbuffer = 0;
10344                 rsurface.passcolor4f_bufferoffset = 0;
10345                 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)
10346                 {
10347                         f = RSurf_FogVertex(v);
10348                         c2[0] = c[0] * f;
10349                         c2[1] = c[1] * f;
10350                         c2[2] = c[2] * f;
10351                         c2[3] = c[3];
10352                 }
10353         }
10354         else
10355         {
10356                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10357                 rsurface.passcolor4f_vertexbuffer = 0;
10358                 rsurface.passcolor4f_bufferoffset = 0;
10359                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10360                 {
10361                         f = RSurf_FogVertex(v);
10362                         c2[0] = f;
10363                         c2[1] = f;
10364                         c2[2] = f;
10365                         c2[3] = 1;
10366                 }
10367         }
10368 }
10369
10370 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10371 {
10372         int i;
10373         float f;
10374         const float *v;
10375         const float *c;
10376         float *c2;
10377         if (!rsurface.passcolor4f)
10378                 return;
10379         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10380         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10381         rsurface.passcolor4f_vertexbuffer = 0;
10382         rsurface.passcolor4f_bufferoffset = 0;
10383         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10384         {
10385                 f = RSurf_FogVertex(v);
10386                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10387                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10388                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10389                 c2[3] = c[3];
10390         }
10391 }
10392
10393 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10394 {
10395         int i;
10396         const float *c;
10397         float *c2;
10398         if (!rsurface.passcolor4f)
10399                 return;
10400         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10401         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10402         rsurface.passcolor4f_vertexbuffer = 0;
10403         rsurface.passcolor4f_bufferoffset = 0;
10404         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10405         {
10406                 c2[0] = c[0] * r;
10407                 c2[1] = c[1] * g;
10408                 c2[2] = c[2] * b;
10409                 c2[3] = c[3] * a;
10410         }
10411 }
10412
10413 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10414 {
10415         int i;
10416         const float *c;
10417         float *c2;
10418         if (!rsurface.passcolor4f)
10419                 return;
10420         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10421         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10422         rsurface.passcolor4f_vertexbuffer = 0;
10423         rsurface.passcolor4f_bufferoffset = 0;
10424         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10425         {
10426                 c2[0] = c[0] + r_refdef.scene.ambient;
10427                 c2[1] = c[1] + r_refdef.scene.ambient;
10428                 c2[2] = c[2] + r_refdef.scene.ambient;
10429                 c2[3] = c[3];
10430         }
10431 }
10432
10433 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10434 {
10435         // TODO: optimize
10436         rsurface.passcolor4f = NULL;
10437         rsurface.passcolor4f_vertexbuffer = 0;
10438         rsurface.passcolor4f_bufferoffset = 0;
10439         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10440         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10441         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10442         GL_Color(r, g, b, a);
10443         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10444         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10445         R_Mesh_TexMatrix(0, NULL);
10446         RSurf_DrawBatch();
10447 }
10448
10449 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10450 {
10451         // TODO: optimize applyfog && applycolor case
10452         // just apply fog if necessary, and tint the fog color array if necessary
10453         rsurface.passcolor4f = NULL;
10454         rsurface.passcolor4f_vertexbuffer = 0;
10455         rsurface.passcolor4f_bufferoffset = 0;
10456         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10457         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10458         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10459         GL_Color(r, g, b, a);
10460         RSurf_DrawBatch();
10461 }
10462
10463 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10464 {
10465         // TODO: optimize
10466         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10467         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10468         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10469         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10470         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10471         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10472         GL_Color(r, g, b, a);
10473         RSurf_DrawBatch();
10474 }
10475
10476 static void RSurf_DrawBatch_GL11_ClampColor(void)
10477 {
10478         int i;
10479         const float *c1;
10480         float *c2;
10481         if (!rsurface.passcolor4f)
10482                 return;
10483         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10484         {
10485                 c2[0] = bound(0.0f, c1[0], 1.0f);
10486                 c2[1] = bound(0.0f, c1[1], 1.0f);
10487                 c2[2] = bound(0.0f, c1[2], 1.0f);
10488                 c2[3] = bound(0.0f, c1[3], 1.0f);
10489         }
10490 }
10491
10492 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10493 {
10494         int i;
10495         float f;
10496         const float *v;
10497         const float *n;
10498         float *c;
10499         //vec3_t eyedir;
10500
10501         // fake shading
10502         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10503         rsurface.passcolor4f_vertexbuffer = 0;
10504         rsurface.passcolor4f_bufferoffset = 0;
10505         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)
10506         {
10507                 f = -DotProduct(r_refdef.view.forward, n);
10508                 f = max(0, f);
10509                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10510                 f *= r_refdef.lightmapintensity;
10511                 Vector4Set(c, f, f, f, 1);
10512         }
10513 }
10514
10515 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10516 {
10517         RSurf_DrawBatch_GL11_ApplyFakeLight();
10518         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10519         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10520         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10521         GL_Color(r, g, b, a);
10522         RSurf_DrawBatch();
10523 }
10524
10525 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10526 {
10527         int i;
10528         float f;
10529         float alpha;
10530         const float *v;
10531         const float *n;
10532         float *c;
10533         vec3_t ambientcolor;
10534         vec3_t diffusecolor;
10535         vec3_t lightdir;
10536         // TODO: optimize
10537         // model lighting
10538         VectorCopy(rsurface.modellight_lightdir, lightdir);
10539         f = 0.5f * r_refdef.lightmapintensity;
10540         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10541         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10542         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10543         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10544         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10545         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10546         alpha = *a;
10547         if (VectorLength2(diffusecolor) > 0)
10548         {
10549                 // q3-style directional shading
10550                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10551                 rsurface.passcolor4f_vertexbuffer = 0;
10552                 rsurface.passcolor4f_bufferoffset = 0;
10553                 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)
10554                 {
10555                         if ((f = DotProduct(n, lightdir)) > 0)
10556                                 VectorMA(ambientcolor, f, diffusecolor, c);
10557                         else
10558                                 VectorCopy(ambientcolor, c);
10559                         c[3] = alpha;
10560                 }
10561                 *r = 1;
10562                 *g = 1;
10563                 *b = 1;
10564                 *a = 1;
10565                 *applycolor = false;
10566         }
10567         else
10568         {
10569                 *r = ambientcolor[0];
10570                 *g = ambientcolor[1];
10571                 *b = ambientcolor[2];
10572                 rsurface.passcolor4f = NULL;
10573                 rsurface.passcolor4f_vertexbuffer = 0;
10574                 rsurface.passcolor4f_bufferoffset = 0;
10575         }
10576 }
10577
10578 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10579 {
10580         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10581         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10582         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10583         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10584         GL_Color(r, g, b, a);
10585         RSurf_DrawBatch();
10586 }
10587
10588 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10589 {
10590         int i;
10591         float f;
10592         const float *v;
10593         float *c;
10594
10595         // fake shading
10596         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10597         rsurface.passcolor4f_vertexbuffer = 0;
10598         rsurface.passcolor4f_bufferoffset = 0;
10599
10600         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10601         {
10602                 f = 1 - RSurf_FogVertex(v);
10603                 c[0] = r;
10604                 c[1] = g;
10605                 c[2] = b;
10606                 c[3] = f * a;
10607         }
10608 }
10609
10610 void RSurf_SetupDepthAndCulling(void)
10611 {
10612         // submodels are biased to avoid z-fighting with world surfaces that they
10613         // may be exactly overlapping (avoids z-fighting artifacts on certain
10614         // doors and things in Quake maps)
10615         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10616         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10617         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10618         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10619 }
10620
10621 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10622 {
10623         // transparent sky would be ridiculous
10624         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10625                 return;
10626         R_SetupShader_Generic_NoTexture(false, false);
10627         skyrenderlater = true;
10628         RSurf_SetupDepthAndCulling();
10629         GL_DepthMask(true);
10630         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10631         // skymasking on them, and Quake3 never did sky masking (unlike
10632         // software Quake and software Quake2), so disable the sky masking
10633         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10634         // and skymasking also looks very bad when noclipping outside the
10635         // level, so don't use it then either.
10636         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10637         {
10638                 R_Mesh_ResetTextureState();
10639                 if (skyrendermasked)
10640                 {
10641                         R_SetupShader_DepthOrShadow(false, false, false);
10642                         // depth-only (masking)
10643                         GL_ColorMask(0,0,0,0);
10644                         // just to make sure that braindead drivers don't draw
10645                         // anything despite that colormask...
10646                         GL_BlendFunc(GL_ZERO, GL_ONE);
10647                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10648                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10649                 }
10650                 else
10651                 {
10652                         R_SetupShader_Generic_NoTexture(false, false);
10653                         // fog sky
10654                         GL_BlendFunc(GL_ONE, GL_ZERO);
10655                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10656                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10657                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10658                 }
10659                 RSurf_DrawBatch();
10660                 if (skyrendermasked)
10661                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10662         }
10663         R_Mesh_ResetTextureState();
10664         GL_Color(1, 1, 1, 1);
10665 }
10666
10667 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10668 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10669 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10670 {
10671         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10672                 return;
10673         if (prepass)
10674         {
10675                 // render screenspace normalmap to texture
10676                 GL_DepthMask(true);
10677                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10678                 RSurf_DrawBatch();
10679                 return;
10680         }
10681
10682         // bind lightmap texture
10683
10684         // water/refraction/reflection/camera surfaces have to be handled specially
10685         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10686         {
10687                 int start, end, startplaneindex;
10688                 for (start = 0;start < texturenumsurfaces;start = end)
10689                 {
10690                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10691                         if(startplaneindex < 0)
10692                         {
10693                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10694                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10695                                 end = start + 1;
10696                                 continue;
10697                         }
10698                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10699                                 ;
10700                         // now that we have a batch using the same planeindex, render it
10701                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10702                         {
10703                                 // render water or distortion background
10704                                 GL_DepthMask(true);
10705                                 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);
10706                                 RSurf_DrawBatch();
10707                                 // blend surface on top
10708                                 GL_DepthMask(false);
10709                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10710                                 RSurf_DrawBatch();
10711                         }
10712                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10713                         {
10714                                 // render surface with reflection texture as input
10715                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10716                                 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);
10717                                 RSurf_DrawBatch();
10718                         }
10719                 }
10720                 return;
10721         }
10722
10723         // render surface batch normally
10724         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10725         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);
10726         RSurf_DrawBatch();
10727 }
10728
10729 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10730 {
10731         // OpenGL 1.3 path - anything not completely ancient
10732         qboolean applycolor;
10733         qboolean applyfog;
10734         int layerindex;
10735         const texturelayer_t *layer;
10736         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);
10737         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10738
10739         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10740         {
10741                 vec4_t layercolor;
10742                 int layertexrgbscale;
10743                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10744                 {
10745                         if (layerindex == 0)
10746                                 GL_AlphaTest(true);
10747                         else
10748                         {
10749                                 GL_AlphaTest(false);
10750                                 GL_DepthFunc(GL_EQUAL);
10751                         }
10752                 }
10753                 GL_DepthMask(layer->depthmask && writedepth);
10754                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10755                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10756                 {
10757                         layertexrgbscale = 4;
10758                         VectorScale(layer->color, 0.25f, layercolor);
10759                 }
10760                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10761                 {
10762                         layertexrgbscale = 2;
10763                         VectorScale(layer->color, 0.5f, layercolor);
10764                 }
10765                 else
10766                 {
10767                         layertexrgbscale = 1;
10768                         VectorScale(layer->color, 1.0f, layercolor);
10769                 }
10770                 layercolor[3] = layer->color[3];
10771                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10772                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10773                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10774                 switch (layer->type)
10775                 {
10776                 case TEXTURELAYERTYPE_LITTEXTURE:
10777                         // single-pass lightmapped texture with 2x rgbscale
10778                         R_Mesh_TexBind(0, r_texture_white);
10779                         R_Mesh_TexMatrix(0, NULL);
10780                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10781                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10782                         R_Mesh_TexBind(1, layer->texture);
10783                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10784                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10785                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10786                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10787                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10788                         else if (FAKELIGHT_ENABLED)
10789                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10790                         else if (rsurface.uselightmaptexture)
10791                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10792                         else
10793                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10794                         break;
10795                 case TEXTURELAYERTYPE_TEXTURE:
10796                         // singletexture unlit texture with transparency support
10797                         R_Mesh_TexBind(0, layer->texture);
10798                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10799                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10800                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10801                         R_Mesh_TexBind(1, 0);
10802                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10803                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10804                         break;
10805                 case TEXTURELAYERTYPE_FOG:
10806                         // singletexture fogging
10807                         if (layer->texture)
10808                         {
10809                                 R_Mesh_TexBind(0, layer->texture);
10810                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10811                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10812                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10813                         }
10814                         else
10815                         {
10816                                 R_Mesh_TexBind(0, 0);
10817                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10818                         }
10819                         R_Mesh_TexBind(1, 0);
10820                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10821                         // generate a color array for the fog pass
10822                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10823                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10824                         RSurf_DrawBatch();
10825                         break;
10826                 default:
10827                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10828                 }
10829         }
10830         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10831         {
10832                 GL_DepthFunc(GL_LEQUAL);
10833                 GL_AlphaTest(false);
10834         }
10835 }
10836
10837 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10838 {
10839         // OpenGL 1.1 - crusty old voodoo path
10840         qboolean applyfog;
10841         int layerindex;
10842         const texturelayer_t *layer;
10843         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);
10844         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10845
10846         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10847         {
10848                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10849                 {
10850                         if (layerindex == 0)
10851                                 GL_AlphaTest(true);
10852                         else
10853                         {
10854                                 GL_AlphaTest(false);
10855                                 GL_DepthFunc(GL_EQUAL);
10856                         }
10857                 }
10858                 GL_DepthMask(layer->depthmask && writedepth);
10859                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10860                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10861                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10862                 switch (layer->type)
10863                 {
10864                 case TEXTURELAYERTYPE_LITTEXTURE:
10865                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10866                         {
10867                                 // two-pass lit texture with 2x rgbscale
10868                                 // first the lightmap pass
10869                                 R_Mesh_TexBind(0, r_texture_white);
10870                                 R_Mesh_TexMatrix(0, NULL);
10871                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10872                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10873                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10874                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10875                                 else if (FAKELIGHT_ENABLED)
10876                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10877                                 else if (rsurface.uselightmaptexture)
10878                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10879                                 else
10880                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10881                                 // then apply the texture to it
10882                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10883                                 R_Mesh_TexBind(0, layer->texture);
10884                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10885                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10886                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10887                                 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);
10888                         }
10889                         else
10890                         {
10891                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10892                                 R_Mesh_TexBind(0, layer->texture);
10893                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10894                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10895                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10896                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10897                                         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);
10898                                 else if (FAKELIGHT_ENABLED)
10899                                         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);
10900                                 else
10901                                         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);
10902                         }
10903                         break;
10904                 case TEXTURELAYERTYPE_TEXTURE:
10905                         // singletexture unlit texture with transparency support
10906                         R_Mesh_TexBind(0, layer->texture);
10907                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10908                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10909                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10910                         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);
10911                         break;
10912                 case TEXTURELAYERTYPE_FOG:
10913                         // singletexture fogging
10914                         if (layer->texture)
10915                         {
10916                                 R_Mesh_TexBind(0, layer->texture);
10917                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10918                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10919                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10920                         }
10921                         else
10922                         {
10923                                 R_Mesh_TexBind(0, 0);
10924                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10925                         }
10926                         // generate a color array for the fog pass
10927                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10928                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10929                         RSurf_DrawBatch();
10930                         break;
10931                 default:
10932                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10933                 }
10934         }
10935         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10936         {
10937                 GL_DepthFunc(GL_LEQUAL);
10938                 GL_AlphaTest(false);
10939         }
10940 }
10941
10942 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10943 {
10944         int vi;
10945         int j;
10946         r_vertexgeneric_t *batchvertex;
10947         float c[4];
10948
10949 //      R_Mesh_ResetTextureState();
10950         R_SetupShader_Generic_NoTexture(false, false);
10951
10952         if(rsurface.texture && rsurface.texture->currentskinframe)
10953         {
10954                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10955                 c[3] *= rsurface.texture->currentalpha;
10956         }
10957         else
10958         {
10959                 c[0] = 1;
10960                 c[1] = 0;
10961                 c[2] = 1;
10962                 c[3] = 1;
10963         }
10964
10965         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10966         {
10967                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10968                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10969                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10970         }
10971
10972         // brighten it up (as texture value 127 means "unlit")
10973         c[0] *= 2 * r_refdef.view.colorscale;
10974         c[1] *= 2 * r_refdef.view.colorscale;
10975         c[2] *= 2 * r_refdef.view.colorscale;
10976
10977         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10978                 c[3] *= r_wateralpha.value;
10979
10980         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10981         {
10982                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10983                 GL_DepthMask(false);
10984         }
10985         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10986         {
10987                 GL_BlendFunc(GL_ONE, GL_ONE);
10988                 GL_DepthMask(false);
10989         }
10990         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10991         {
10992                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10993                 GL_DepthMask(false);
10994         }
10995         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10996         {
10997                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10998                 GL_DepthMask(false);
10999         }
11000         else
11001         {
11002                 GL_BlendFunc(GL_ONE, GL_ZERO);
11003                 GL_DepthMask(writedepth);
11004         }
11005
11006         if (r_showsurfaces.integer == 3)
11007         {
11008                 rsurface.passcolor4f = NULL;
11009
11010                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11011                 {
11012                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11013
11014                         rsurface.passcolor4f = NULL;
11015                         rsurface.passcolor4f_vertexbuffer = 0;
11016                         rsurface.passcolor4f_bufferoffset = 0;
11017                 }
11018                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11019                 {
11020                         qboolean applycolor = true;
11021                         float one = 1.0;
11022
11023                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11024
11025                         r_refdef.lightmapintensity = 1;
11026                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11027                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11028                 }
11029                 else if (FAKELIGHT_ENABLED)
11030                 {
11031                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11032
11033                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11034                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11035                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11036                 }
11037                 else
11038                 {
11039                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11040
11041                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11042                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11043                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11044                 }
11045
11046                 if(!rsurface.passcolor4f)
11047                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11048
11049                 RSurf_DrawBatch_GL11_ApplyAmbient();
11050                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11051                 if(r_refdef.fogenabled)
11052                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11053                 RSurf_DrawBatch_GL11_ClampColor();
11054
11055                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11056                 R_SetupShader_Generic_NoTexture(false, false);
11057                 RSurf_DrawBatch();
11058         }
11059         else if (!r_refdef.view.showdebug)
11060         {
11061                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11062                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11063                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11064                 {
11065                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11066                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11067                 }
11068                 R_Mesh_PrepareVertices_Generic_Unlock();
11069                 RSurf_DrawBatch();
11070         }
11071         else if (r_showsurfaces.integer == 4)
11072         {
11073                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11074                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11075                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11076                 {
11077                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11078                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11079                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11080                 }
11081                 R_Mesh_PrepareVertices_Generic_Unlock();
11082                 RSurf_DrawBatch();
11083         }
11084         else if (r_showsurfaces.integer == 2)
11085         {
11086                 const int *e;
11087                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11088                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11089                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11090                 {
11091                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11092                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11093                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11094                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11095                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11096                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11097                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11098                 }
11099                 R_Mesh_PrepareVertices_Generic_Unlock();
11100                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11101         }
11102         else
11103         {
11104                 int texturesurfaceindex;
11105                 int k;
11106                 const msurface_t *surface;
11107                 float surfacecolor4f[4];
11108                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11109                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11110                 vi = 0;
11111                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11112                 {
11113                         surface = texturesurfacelist[texturesurfaceindex];
11114                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11115                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11116                         for (j = 0;j < surface->num_vertices;j++)
11117                         {
11118                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11119                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11120                                 vi++;
11121                         }
11122                 }
11123                 R_Mesh_PrepareVertices_Generic_Unlock();
11124                 RSurf_DrawBatch();
11125         }
11126 }
11127
11128 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11129 {
11130         CHECKGLERROR
11131         RSurf_SetupDepthAndCulling();
11132         if (r_showsurfaces.integer)
11133         {
11134                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11135                 return;
11136         }
11137         switch (vid.renderpath)
11138         {
11139         case RENDERPATH_GL20:
11140         case RENDERPATH_D3D9:
11141         case RENDERPATH_D3D10:
11142         case RENDERPATH_D3D11:
11143         case RENDERPATH_SOFT:
11144         case RENDERPATH_GLES2:
11145                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11146                 break;
11147         case RENDERPATH_GL13:
11148         case RENDERPATH_GLES1:
11149                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11150                 break;
11151         case RENDERPATH_GL11:
11152                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11153                 break;
11154         }
11155         CHECKGLERROR
11156 }
11157
11158 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11159 {
11160         CHECKGLERROR
11161         RSurf_SetupDepthAndCulling();
11162         if (r_showsurfaces.integer)
11163         {
11164                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11165                 return;
11166         }
11167         switch (vid.renderpath)
11168         {
11169         case RENDERPATH_GL20:
11170         case RENDERPATH_D3D9:
11171         case RENDERPATH_D3D10:
11172         case RENDERPATH_D3D11:
11173         case RENDERPATH_SOFT:
11174         case RENDERPATH_GLES2:
11175                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11176                 break;
11177         case RENDERPATH_GL13:
11178         case RENDERPATH_GLES1:
11179                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11180                 break;
11181         case RENDERPATH_GL11:
11182                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11183                 break;
11184         }
11185         CHECKGLERROR
11186 }
11187
11188 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11189 {
11190         int i, j;
11191         int texturenumsurfaces, endsurface;
11192         texture_t *texture;
11193         const msurface_t *surface;
11194         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11195
11196         // if the model is static it doesn't matter what value we give for
11197         // wantnormals and wanttangents, so this logic uses only rules applicable
11198         // to a model, knowing that they are meaningless otherwise
11199         if (ent == r_refdef.scene.worldentity)
11200                 RSurf_ActiveWorldEntity();
11201         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11202                 RSurf_ActiveModelEntity(ent, false, false, false);
11203         else
11204         {
11205                 switch (vid.renderpath)
11206                 {
11207                 case RENDERPATH_GL20:
11208                 case RENDERPATH_D3D9:
11209                 case RENDERPATH_D3D10:
11210                 case RENDERPATH_D3D11:
11211                 case RENDERPATH_SOFT:
11212                 case RENDERPATH_GLES2:
11213                         RSurf_ActiveModelEntity(ent, true, true, false);
11214                         break;
11215                 case RENDERPATH_GL11:
11216                 case RENDERPATH_GL13:
11217                 case RENDERPATH_GLES1:
11218                         RSurf_ActiveModelEntity(ent, true, false, false);
11219                         break;
11220                 }
11221         }
11222
11223         if (r_transparentdepthmasking.integer)
11224         {
11225                 qboolean setup = false;
11226                 for (i = 0;i < numsurfaces;i = j)
11227                 {
11228                         j = i + 1;
11229                         surface = rsurface.modelsurfaces + surfacelist[i];
11230                         texture = surface->texture;
11231                         rsurface.texture = R_GetCurrentTexture(texture);
11232                         rsurface.lightmaptexture = NULL;
11233                         rsurface.deluxemaptexture = NULL;
11234                         rsurface.uselightmaptexture = false;
11235                         // scan ahead until we find a different texture
11236                         endsurface = min(i + 1024, numsurfaces);
11237                         texturenumsurfaces = 0;
11238                         texturesurfacelist[texturenumsurfaces++] = surface;
11239                         for (;j < endsurface;j++)
11240                         {
11241                                 surface = rsurface.modelsurfaces + surfacelist[j];
11242                                 if (texture != surface->texture)
11243                                         break;
11244                                 texturesurfacelist[texturenumsurfaces++] = surface;
11245                         }
11246                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11247                                 continue;
11248                         // render the range of surfaces as depth
11249                         if (!setup)
11250                         {
11251                                 setup = true;
11252                                 GL_ColorMask(0,0,0,0);
11253                                 GL_Color(1,1,1,1);
11254                                 GL_DepthTest(true);
11255                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11256                                 GL_DepthMask(true);
11257 //                              R_Mesh_ResetTextureState();
11258                         }
11259                         RSurf_SetupDepthAndCulling();
11260                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11261                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11262                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11263                         RSurf_DrawBatch();
11264                 }
11265                 if (setup)
11266                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11267         }
11268
11269         for (i = 0;i < numsurfaces;i = j)
11270         {
11271                 j = i + 1;
11272                 surface = rsurface.modelsurfaces + surfacelist[i];
11273                 texture = surface->texture;
11274                 rsurface.texture = R_GetCurrentTexture(texture);
11275                 // scan ahead until we find a different texture
11276                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11277                 texturenumsurfaces = 0;
11278                 texturesurfacelist[texturenumsurfaces++] = surface;
11279                 if(FAKELIGHT_ENABLED)
11280                 {
11281                         rsurface.lightmaptexture = NULL;
11282                         rsurface.deluxemaptexture = NULL;
11283                         rsurface.uselightmaptexture = false;
11284                         for (;j < endsurface;j++)
11285                         {
11286                                 surface = rsurface.modelsurfaces + surfacelist[j];
11287                                 if (texture != surface->texture)
11288                                         break;
11289                                 texturesurfacelist[texturenumsurfaces++] = surface;
11290                         }
11291                 }
11292                 else
11293                 {
11294                         rsurface.lightmaptexture = surface->lightmaptexture;
11295                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11296                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11297                         for (;j < endsurface;j++)
11298                         {
11299                                 surface = rsurface.modelsurfaces + surfacelist[j];
11300                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11301                                         break;
11302                                 texturesurfacelist[texturenumsurfaces++] = surface;
11303                         }
11304                 }
11305                 // render the range of surfaces
11306                 if (ent == r_refdef.scene.worldentity)
11307                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11308                 else
11309                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11310         }
11311         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11312 }
11313
11314 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11315 {
11316         // transparent surfaces get pushed off into the transparent queue
11317         int surfacelistindex;
11318         const msurface_t *surface;
11319         vec3_t tempcenter, center;
11320         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11321         {
11322                 surface = texturesurfacelist[surfacelistindex];
11323                 if (r_transparent_sortsurfacesbynearest.integer)
11324                 {
11325                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11326                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11327                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11328                 }
11329                 else
11330                 {
11331                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11332                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11333                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11334                 }
11335                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11336                 if (rsurface.entity->transparent_offset) // transparent offset
11337                 {
11338                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11339                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11340                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11341                 }
11342                 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);
11343         }
11344 }
11345
11346 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11347 {
11348         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11349                 return;
11350         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11351                 return;
11352         RSurf_SetupDepthAndCulling();
11353         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11354         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11355         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11356         RSurf_DrawBatch();
11357 }
11358
11359 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11360 {
11361         CHECKGLERROR
11362         if (depthonly)
11363                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11364         else if (prepass)
11365         {
11366                 if (!rsurface.texture->currentnumlayers)
11367                         return;
11368                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11369                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11370                 else
11371                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11372         }
11373         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11374                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11375         else if (!rsurface.texture->currentnumlayers)
11376                 return;
11377         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11378         {
11379                 // in the deferred case, transparent surfaces were queued during prepass
11380                 if (!r_shadow_usingdeferredprepass)
11381                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11382         }
11383         else
11384         {
11385                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11386                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11387         }
11388         CHECKGLERROR
11389 }
11390
11391 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11392 {
11393         int i, j;
11394         texture_t *texture;
11395         R_FrameData_SetMark();
11396         // break the surface list down into batches by texture and use of lightmapping
11397         for (i = 0;i < numsurfaces;i = j)
11398         {
11399                 j = i + 1;
11400                 // texture is the base texture pointer, rsurface.texture is the
11401                 // current frame/skin the texture is directing us to use (for example
11402                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11403                 // use skin 1 instead)
11404                 texture = surfacelist[i]->texture;
11405                 rsurface.texture = R_GetCurrentTexture(texture);
11406                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11407                 {
11408                         // if this texture is not the kind we want, skip ahead to the next one
11409                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11410                                 ;
11411                         continue;
11412                 }
11413                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11414                 {
11415                         rsurface.lightmaptexture = NULL;
11416                         rsurface.deluxemaptexture = NULL;
11417                         rsurface.uselightmaptexture = false;
11418                         // simply scan ahead until we find a different texture or lightmap state
11419                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11420                                 ;
11421                 }
11422                 else
11423                 {
11424                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11425                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11426                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11427                         // simply scan ahead until we find a different texture or lightmap state
11428                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11429                                 ;
11430                 }
11431                 // render the range of surfaces
11432                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11433         }
11434         R_FrameData_ReturnToMark();
11435 }
11436
11437 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11438 {
11439         CHECKGLERROR
11440         if (depthonly)
11441                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11442         else if (prepass)
11443         {
11444                 if (!rsurface.texture->currentnumlayers)
11445                         return;
11446                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11447                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11448                 else
11449                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11450         }
11451         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11452                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11453         else if (!rsurface.texture->currentnumlayers)
11454                 return;
11455         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11456         {
11457                 // in the deferred case, transparent surfaces were queued during prepass
11458                 if (!r_shadow_usingdeferredprepass)
11459                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11460         }
11461         else
11462         {
11463                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11464                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11465         }
11466         CHECKGLERROR
11467 }
11468
11469 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11470 {
11471         int i, j;
11472         texture_t *texture;
11473         R_FrameData_SetMark();
11474         // break the surface list down into batches by texture and use of lightmapping
11475         for (i = 0;i < numsurfaces;i = j)
11476         {
11477                 j = i + 1;
11478                 // texture is the base texture pointer, rsurface.texture is the
11479                 // current frame/skin the texture is directing us to use (for example
11480                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11481                 // use skin 1 instead)
11482                 texture = surfacelist[i]->texture;
11483                 rsurface.texture = R_GetCurrentTexture(texture);
11484                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11485                 {
11486                         // if this texture is not the kind we want, skip ahead to the next one
11487                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11488                                 ;
11489                         continue;
11490                 }
11491                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11492                 {
11493                         rsurface.lightmaptexture = NULL;
11494                         rsurface.deluxemaptexture = NULL;
11495                         rsurface.uselightmaptexture = false;
11496                         // simply scan ahead until we find a different texture or lightmap state
11497                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11498                                 ;
11499                 }
11500                 else
11501                 {
11502                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11503                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11504                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11505                         // simply scan ahead until we find a different texture or lightmap state
11506                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11507                                 ;
11508                 }
11509                 // render the range of surfaces
11510                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11511         }
11512         R_FrameData_ReturnToMark();
11513 }
11514
11515 float locboxvertex3f[6*4*3] =
11516 {
11517         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11518         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11519         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11520         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11521         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11522         1,0,0, 0,0,0, 0,1,0, 1,1,0
11523 };
11524
11525 unsigned short locboxelements[6*2*3] =
11526 {
11527          0, 1, 2, 0, 2, 3,
11528          4, 5, 6, 4, 6, 7,
11529          8, 9,10, 8,10,11,
11530         12,13,14, 12,14,15,
11531         16,17,18, 16,18,19,
11532         20,21,22, 20,22,23
11533 };
11534
11535 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11536 {
11537         int i, j;
11538         cl_locnode_t *loc = (cl_locnode_t *)ent;
11539         vec3_t mins, size;
11540         float vertex3f[6*4*3];
11541         CHECKGLERROR
11542         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11543         GL_DepthMask(false);
11544         GL_DepthRange(0, 1);
11545         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11546         GL_DepthTest(true);
11547         GL_CullFace(GL_NONE);
11548         R_EntityMatrix(&identitymatrix);
11549
11550 //      R_Mesh_ResetTextureState();
11551
11552         i = surfacelist[0];
11553         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11554                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11555                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11556                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11557
11558         if (VectorCompare(loc->mins, loc->maxs))
11559         {
11560                 VectorSet(size, 2, 2, 2);
11561                 VectorMA(loc->mins, -0.5f, size, mins);
11562         }
11563         else
11564         {
11565                 VectorCopy(loc->mins, mins);
11566                 VectorSubtract(loc->maxs, loc->mins, size);
11567         }
11568
11569         for (i = 0;i < 6*4*3;)
11570                 for (j = 0;j < 3;j++, i++)
11571                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11572
11573         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11574         R_SetupShader_Generic_NoTexture(false, false);
11575         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11576 }
11577
11578 void R_DrawLocs(void)
11579 {
11580         int index;
11581         cl_locnode_t *loc, *nearestloc;
11582         vec3_t center;
11583         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11584         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11585         {
11586                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11587                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11588         }
11589 }
11590
11591 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11592 {
11593         if (decalsystem->decals)
11594                 Mem_Free(decalsystem->decals);
11595         memset(decalsystem, 0, sizeof(*decalsystem));
11596 }
11597
11598 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)
11599 {
11600         tridecal_t *decal;
11601         tridecal_t *decals;
11602         int i;
11603
11604         // expand or initialize the system
11605         if (decalsystem->maxdecals <= decalsystem->numdecals)
11606         {
11607                 decalsystem_t old = *decalsystem;
11608                 qboolean useshortelements;
11609                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11610                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11611                 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)));
11612                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11613                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11614                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11615                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11616                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11617                 if (decalsystem->numdecals)
11618                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11619                 if (old.decals)
11620                         Mem_Free(old.decals);
11621                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11622                         decalsystem->element3i[i] = i;
11623                 if (useshortelements)
11624                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11625                                 decalsystem->element3s[i] = i;
11626         }
11627
11628         // grab a decal and search for another free slot for the next one
11629         decals = decalsystem->decals;
11630         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11631         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11632                 ;
11633         decalsystem->freedecal = i;
11634         if (decalsystem->numdecals <= i)
11635                 decalsystem->numdecals = i + 1;
11636
11637         // initialize the decal
11638         decal->lived = 0;
11639         decal->triangleindex = triangleindex;
11640         decal->surfaceindex = surfaceindex;
11641         decal->decalsequence = decalsequence;
11642         decal->color4f[0][0] = c0[0];
11643         decal->color4f[0][1] = c0[1];
11644         decal->color4f[0][2] = c0[2];
11645         decal->color4f[0][3] = 1;
11646         decal->color4f[1][0] = c1[0];
11647         decal->color4f[1][1] = c1[1];
11648         decal->color4f[1][2] = c1[2];
11649         decal->color4f[1][3] = 1;
11650         decal->color4f[2][0] = c2[0];
11651         decal->color4f[2][1] = c2[1];
11652         decal->color4f[2][2] = c2[2];
11653         decal->color4f[2][3] = 1;
11654         decal->vertex3f[0][0] = v0[0];
11655         decal->vertex3f[0][1] = v0[1];
11656         decal->vertex3f[0][2] = v0[2];
11657         decal->vertex3f[1][0] = v1[0];
11658         decal->vertex3f[1][1] = v1[1];
11659         decal->vertex3f[1][2] = v1[2];
11660         decal->vertex3f[2][0] = v2[0];
11661         decal->vertex3f[2][1] = v2[1];
11662         decal->vertex3f[2][2] = v2[2];
11663         decal->texcoord2f[0][0] = t0[0];
11664         decal->texcoord2f[0][1] = t0[1];
11665         decal->texcoord2f[1][0] = t1[0];
11666         decal->texcoord2f[1][1] = t1[1];
11667         decal->texcoord2f[2][0] = t2[0];
11668         decal->texcoord2f[2][1] = t2[1];
11669         TriangleNormal(v0, v1, v2, decal->plane);
11670         VectorNormalize(decal->plane);
11671         decal->plane[3] = DotProduct(v0, decal->plane);
11672 }
11673
11674 extern cvar_t cl_decals_bias;
11675 extern cvar_t cl_decals_models;
11676 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11677 // baseparms, parms, temps
11678 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)
11679 {
11680         int cornerindex;
11681         int index;
11682         float v[9][3];
11683         const float *vertex3f;
11684         const float *normal3f;
11685         int numpoints;
11686         float points[2][9][3];
11687         float temp[3];
11688         float tc[9][2];
11689         float f;
11690         float c[9][4];
11691         const int *e;
11692
11693         e = rsurface.modelelement3i + 3*triangleindex;
11694
11695         vertex3f = rsurface.modelvertex3f;
11696         normal3f = rsurface.modelnormal3f;
11697
11698         if (normal3f)
11699         {
11700                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11701                 {
11702                         index = 3*e[cornerindex];
11703                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11704                 }
11705         }
11706         else
11707         {
11708                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11709                 {
11710                         index = 3*e[cornerindex];
11711                         VectorCopy(vertex3f + index, v[cornerindex]);
11712                 }
11713         }
11714
11715         // cull backfaces
11716         //TriangleNormal(v[0], v[1], v[2], normal);
11717         //if (DotProduct(normal, localnormal) < 0.0f)
11718         //      continue;
11719         // clip by each of the box planes formed from the projection matrix
11720         // if anything survives, we emit the decal
11721         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]);
11722         if (numpoints < 3)
11723                 return;
11724         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]);
11725         if (numpoints < 3)
11726                 return;
11727         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]);
11728         if (numpoints < 3)
11729                 return;
11730         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]);
11731         if (numpoints < 3)
11732                 return;
11733         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]);
11734         if (numpoints < 3)
11735                 return;
11736         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]);
11737         if (numpoints < 3)
11738                 return;
11739         // some part of the triangle survived, so we have to accept it...
11740         if (dynamic)
11741         {
11742                 // dynamic always uses the original triangle
11743                 numpoints = 3;
11744                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11745                 {
11746                         index = 3*e[cornerindex];
11747                         VectorCopy(vertex3f + index, v[cornerindex]);
11748                 }
11749         }
11750         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11751         {
11752                 // convert vertex positions to texcoords
11753                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11754                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11755                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11756                 // calculate distance fade from the projection origin
11757                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11758                 f = bound(0.0f, f, 1.0f);
11759                 c[cornerindex][0] = r * f;
11760                 c[cornerindex][1] = g * f;
11761                 c[cornerindex][2] = b * f;
11762                 c[cornerindex][3] = 1.0f;
11763                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11764         }
11765         if (dynamic)
11766                 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);
11767         else
11768                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11769                         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);
11770 }
11771 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)
11772 {
11773         matrix4x4_t projection;
11774         decalsystem_t *decalsystem;
11775         qboolean dynamic;
11776         dp_model_t *model;
11777         const msurface_t *surface;
11778         const msurface_t *surfaces;
11779         const int *surfacelist;
11780         const texture_t *texture;
11781         int numtriangles;
11782         int numsurfacelist;
11783         int surfacelistindex;
11784         int surfaceindex;
11785         int triangleindex;
11786         float localorigin[3];
11787         float localnormal[3];
11788         float localmins[3];
11789         float localmaxs[3];
11790         float localsize;
11791         //float normal[3];
11792         float planes[6][4];
11793         float angles[3];
11794         bih_t *bih;
11795         int bih_triangles_count;
11796         int bih_triangles[256];
11797         int bih_surfaces[256];
11798
11799         decalsystem = &ent->decalsystem;
11800         model = ent->model;
11801         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11802         {
11803                 R_DecalSystem_Reset(&ent->decalsystem);
11804                 return;
11805         }
11806
11807         if (!model->brush.data_leafs && !cl_decals_models.integer)
11808         {
11809                 if (decalsystem->model)
11810                         R_DecalSystem_Reset(decalsystem);
11811                 return;
11812         }
11813
11814         if (decalsystem->model != model)
11815                 R_DecalSystem_Reset(decalsystem);
11816         decalsystem->model = model;
11817
11818         RSurf_ActiveModelEntity(ent, true, false, false);
11819
11820         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11821         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11822         VectorNormalize(localnormal);
11823         localsize = worldsize*rsurface.inversematrixscale;
11824         localmins[0] = localorigin[0] - localsize;
11825         localmins[1] = localorigin[1] - localsize;
11826         localmins[2] = localorigin[2] - localsize;
11827         localmaxs[0] = localorigin[0] + localsize;
11828         localmaxs[1] = localorigin[1] + localsize;
11829         localmaxs[2] = localorigin[2] + localsize;
11830
11831         //VectorCopy(localnormal, planes[4]);
11832         //VectorVectors(planes[4], planes[2], planes[0]);
11833         AnglesFromVectors(angles, localnormal, NULL, false);
11834         AngleVectors(angles, planes[0], planes[2], planes[4]);
11835         VectorNegate(planes[0], planes[1]);
11836         VectorNegate(planes[2], planes[3]);
11837         VectorNegate(planes[4], planes[5]);
11838         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11839         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11840         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11841         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11842         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11843         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11844
11845 #if 1
11846 // works
11847 {
11848         matrix4x4_t forwardprojection;
11849         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11850         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11851 }
11852 #else
11853 // broken
11854 {
11855         float projectionvector[4][3];
11856         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11857         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11858         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11859         projectionvector[0][0] = planes[0][0] * ilocalsize;
11860         projectionvector[0][1] = planes[1][0] * ilocalsize;
11861         projectionvector[0][2] = planes[2][0] * ilocalsize;
11862         projectionvector[1][0] = planes[0][1] * ilocalsize;
11863         projectionvector[1][1] = planes[1][1] * ilocalsize;
11864         projectionvector[1][2] = planes[2][1] * ilocalsize;
11865         projectionvector[2][0] = planes[0][2] * ilocalsize;
11866         projectionvector[2][1] = planes[1][2] * ilocalsize;
11867         projectionvector[2][2] = planes[2][2] * ilocalsize;
11868         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11869         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11870         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11871         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11872 }
11873 #endif
11874
11875         dynamic = model->surfmesh.isanimated;
11876         numsurfacelist = model->nummodelsurfaces;
11877         surfacelist = model->sortedmodelsurfaces;
11878         surfaces = model->data_surfaces;
11879
11880         bih = NULL;
11881         bih_triangles_count = -1;
11882         if(!dynamic)
11883         {
11884                 if(model->render_bih.numleafs)
11885                         bih = &model->render_bih;
11886                 else if(model->collision_bih.numleafs)
11887                         bih = &model->collision_bih;
11888         }
11889         if(bih)
11890                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11891         if(bih_triangles_count == 0)
11892                 return;
11893         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11894                 return;
11895         if(bih_triangles_count > 0)
11896         {
11897                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11898                 {
11899                         surfaceindex = bih_surfaces[triangleindex];
11900                         surface = surfaces + surfaceindex;
11901                         texture = surface->texture;
11902                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11903                                 continue;
11904                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11905                                 continue;
11906                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11907                 }
11908         }
11909         else
11910         {
11911                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11912                 {
11913                         surfaceindex = surfacelist[surfacelistindex];
11914                         surface = surfaces + surfaceindex;
11915                         // check cull box first because it rejects more than any other check
11916                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11917                                 continue;
11918                         // skip transparent surfaces
11919                         texture = surface->texture;
11920                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11921                                 continue;
11922                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11923                                 continue;
11924                         numtriangles = surface->num_triangles;
11925                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11926                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11927                 }
11928         }
11929 }
11930
11931 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11932 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)
11933 {
11934         int renderentityindex;
11935         float worldmins[3];
11936         float worldmaxs[3];
11937         entity_render_t *ent;
11938
11939         if (!cl_decals_newsystem.integer)
11940                 return;
11941
11942         worldmins[0] = worldorigin[0] - worldsize;
11943         worldmins[1] = worldorigin[1] - worldsize;
11944         worldmins[2] = worldorigin[2] - worldsize;
11945         worldmaxs[0] = worldorigin[0] + worldsize;
11946         worldmaxs[1] = worldorigin[1] + worldsize;
11947         worldmaxs[2] = worldorigin[2] + worldsize;
11948
11949         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11950
11951         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11952         {
11953                 ent = r_refdef.scene.entities[renderentityindex];
11954                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11955                         continue;
11956
11957                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11958         }
11959 }
11960
11961 typedef struct r_decalsystem_splatqueue_s
11962 {
11963         vec3_t worldorigin;
11964         vec3_t worldnormal;
11965         float color[4];
11966         float tcrange[4];
11967         float worldsize;
11968         int decalsequence;
11969 }
11970 r_decalsystem_splatqueue_t;
11971
11972 int r_decalsystem_numqueued = 0;
11973 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11974
11975 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)
11976 {
11977         r_decalsystem_splatqueue_t *queue;
11978
11979         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11980                 return;
11981
11982         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11983         VectorCopy(worldorigin, queue->worldorigin);
11984         VectorCopy(worldnormal, queue->worldnormal);
11985         Vector4Set(queue->color, r, g, b, a);
11986         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11987         queue->worldsize = worldsize;
11988         queue->decalsequence = cl.decalsequence++;
11989 }
11990
11991 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11992 {
11993         int i;
11994         r_decalsystem_splatqueue_t *queue;
11995
11996         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11997                 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);
11998         r_decalsystem_numqueued = 0;
11999 }
12000
12001 extern cvar_t cl_decals_max;
12002 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12003 {
12004         int i;
12005         decalsystem_t *decalsystem = &ent->decalsystem;
12006         int numdecals;
12007         int killsequence;
12008         tridecal_t *decal;
12009         float frametime;
12010         float lifetime;
12011
12012         if (!decalsystem->numdecals)
12013                 return;
12014
12015         if (r_showsurfaces.integer)
12016                 return;
12017
12018         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12019         {
12020                 R_DecalSystem_Reset(decalsystem);
12021                 return;
12022         }
12023
12024         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12025         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12026
12027         if (decalsystem->lastupdatetime)
12028                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12029         else
12030                 frametime = 0;
12031         decalsystem->lastupdatetime = r_refdef.scene.time;
12032         numdecals = decalsystem->numdecals;
12033
12034         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12035         {
12036                 if (decal->color4f[0][3])
12037                 {
12038                         decal->lived += frametime;
12039                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12040                         {
12041                                 memset(decal, 0, sizeof(*decal));
12042                                 if (decalsystem->freedecal > i)
12043                                         decalsystem->freedecal = i;
12044                         }
12045                 }
12046         }
12047         decal = decalsystem->decals;
12048         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12049                 numdecals--;
12050
12051         // collapse the array by shuffling the tail decals into the gaps
12052         for (;;)
12053         {
12054                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12055                         decalsystem->freedecal++;
12056                 if (decalsystem->freedecal == numdecals)
12057                         break;
12058                 decal[decalsystem->freedecal] = decal[--numdecals];
12059         }
12060
12061         decalsystem->numdecals = numdecals;
12062
12063         if (numdecals <= 0)
12064         {
12065                 // if there are no decals left, reset decalsystem
12066                 R_DecalSystem_Reset(decalsystem);
12067         }
12068 }
12069
12070 extern skinframe_t *decalskinframe;
12071 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12072 {
12073         int i;
12074         decalsystem_t *decalsystem = &ent->decalsystem;
12075         int numdecals;
12076         tridecal_t *decal;
12077         float faderate;
12078         float alpha;
12079         float *v3f;
12080         float *c4f;
12081         float *t2f;
12082         const int *e;
12083         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12084         int numtris = 0;
12085
12086         numdecals = decalsystem->numdecals;
12087         if (!numdecals)
12088                 return;
12089
12090         if (r_showsurfaces.integer)
12091                 return;
12092
12093         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12094         {
12095                 R_DecalSystem_Reset(decalsystem);
12096                 return;
12097         }
12098
12099         // if the model is static it doesn't matter what value we give for
12100         // wantnormals and wanttangents, so this logic uses only rules applicable
12101         // to a model, knowing that they are meaningless otherwise
12102         if (ent == r_refdef.scene.worldentity)
12103                 RSurf_ActiveWorldEntity();
12104         else
12105                 RSurf_ActiveModelEntity(ent, false, false, false);
12106
12107         decalsystem->lastupdatetime = r_refdef.scene.time;
12108
12109         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12110
12111         // update vertex positions for animated models
12112         v3f = decalsystem->vertex3f;
12113         c4f = decalsystem->color4f;
12114         t2f = decalsystem->texcoord2f;
12115         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12116         {
12117                 if (!decal->color4f[0][3])
12118                         continue;
12119
12120                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12121                         continue;
12122
12123                 // skip backfaces
12124                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12125                         continue;
12126
12127                 // update color values for fading decals
12128                 if (decal->lived >= cl_decals_time.value)
12129                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12130                 else
12131                         alpha = 1.0f;
12132
12133                 c4f[ 0] = decal->color4f[0][0] * alpha;
12134                 c4f[ 1] = decal->color4f[0][1] * alpha;
12135                 c4f[ 2] = decal->color4f[0][2] * alpha;
12136                 c4f[ 3] = 1;
12137                 c4f[ 4] = decal->color4f[1][0] * alpha;
12138                 c4f[ 5] = decal->color4f[1][1] * alpha;
12139                 c4f[ 6] = decal->color4f[1][2] * alpha;
12140                 c4f[ 7] = 1;
12141                 c4f[ 8] = decal->color4f[2][0] * alpha;
12142                 c4f[ 9] = decal->color4f[2][1] * alpha;
12143                 c4f[10] = decal->color4f[2][2] * alpha;
12144                 c4f[11] = 1;
12145
12146                 t2f[0] = decal->texcoord2f[0][0];
12147                 t2f[1] = decal->texcoord2f[0][1];
12148                 t2f[2] = decal->texcoord2f[1][0];
12149                 t2f[3] = decal->texcoord2f[1][1];
12150                 t2f[4] = decal->texcoord2f[2][0];
12151                 t2f[5] = decal->texcoord2f[2][1];
12152
12153                 // update vertex positions for animated models
12154                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12155                 {
12156                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12157                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12158                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12159                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12160                 }
12161                 else
12162                 {
12163                         VectorCopy(decal->vertex3f[0], v3f);
12164                         VectorCopy(decal->vertex3f[1], v3f + 3);
12165                         VectorCopy(decal->vertex3f[2], v3f + 6);
12166                 }
12167
12168                 if (r_refdef.fogenabled)
12169                 {
12170                         alpha = RSurf_FogVertex(v3f);
12171                         VectorScale(c4f, alpha, c4f);
12172                         alpha = RSurf_FogVertex(v3f + 3);
12173                         VectorScale(c4f + 4, alpha, c4f + 4);
12174                         alpha = RSurf_FogVertex(v3f + 6);
12175                         VectorScale(c4f + 8, alpha, c4f + 8);
12176                 }
12177
12178                 v3f += 9;
12179                 c4f += 12;
12180                 t2f += 6;
12181                 numtris++;
12182         }
12183
12184         if (numtris > 0)
12185         {
12186                 r_refdef.stats[r_stat_drawndecals] += numtris;
12187
12188                 // now render the decals all at once
12189                 // (this assumes they all use one particle font texture!)
12190                 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);
12191 //              R_Mesh_ResetTextureState();
12192                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12193                 GL_DepthMask(false);
12194                 GL_DepthRange(0, 1);
12195                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12196                 GL_DepthTest(true);
12197                 GL_CullFace(GL_NONE);
12198                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12199                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12200                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12201         }
12202 }
12203
12204 static void R_DrawModelDecals(void)
12205 {
12206         int i, numdecals;
12207
12208         // fade faster when there are too many decals
12209         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12210         for (i = 0;i < r_refdef.scene.numentities;i++)
12211                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12212
12213         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12214         for (i = 0;i < r_refdef.scene.numentities;i++)
12215                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12216                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12217
12218         R_DecalSystem_ApplySplatEntitiesQueue();
12219
12220         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12221         for (i = 0;i < r_refdef.scene.numentities;i++)
12222                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12223
12224         r_refdef.stats[r_stat_totaldecals] += numdecals;
12225
12226         if (r_showsurfaces.integer)
12227                 return;
12228
12229         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12230
12231         for (i = 0;i < r_refdef.scene.numentities;i++)
12232         {
12233                 if (!r_refdef.viewcache.entityvisible[i])
12234                         continue;
12235                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12236                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12237         }
12238 }
12239
12240 extern cvar_t mod_collision_bih;
12241 static void R_DrawDebugModel(void)
12242 {
12243         entity_render_t *ent = rsurface.entity;
12244         int i, j, flagsmask;
12245         const msurface_t *surface;
12246         dp_model_t *model = ent->model;
12247
12248         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12249                 return;
12250
12251         if (r_showoverdraw.value > 0)
12252         {
12253                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12254                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12255                 R_SetupShader_Generic_NoTexture(false, false);
12256                 GL_DepthTest(false);
12257                 GL_DepthMask(false);
12258                 GL_DepthRange(0, 1);
12259                 GL_BlendFunc(GL_ONE, GL_ONE);
12260                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12261                 {
12262                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12263                                 continue;
12264                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12265                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12266                         {
12267                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12268                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12269                                 if (!rsurface.texture->currentlayers->depthmask)
12270                                         GL_Color(c, 0, 0, 1.0f);
12271                                 else if (ent == r_refdef.scene.worldentity)
12272                                         GL_Color(c, c, c, 1.0f);
12273                                 else
12274                                         GL_Color(0, c, 0, 1.0f);
12275                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12276                                 RSurf_DrawBatch();
12277                         }
12278                 }
12279                 rsurface.texture = NULL;
12280         }
12281
12282         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12283
12284 //      R_Mesh_ResetTextureState();
12285         R_SetupShader_Generic_NoTexture(false, false);
12286         GL_DepthRange(0, 1);
12287         GL_DepthTest(!r_showdisabledepthtest.integer);
12288         GL_DepthMask(false);
12289         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12290
12291         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12292         {
12293                 int triangleindex;
12294                 int bihleafindex;
12295                 qboolean cullbox = false;
12296                 const q3mbrush_t *brush;
12297                 const bih_t *bih = &model->collision_bih;
12298                 const bih_leaf_t *bihleaf;
12299                 float vertex3f[3][3];
12300                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12301                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12302                 {
12303                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12304                                 continue;
12305                         switch (bihleaf->type)
12306                         {
12307                         case BIH_BRUSH:
12308                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12309                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12310                                 {
12311                                         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);
12312                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12313                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12314                                 }
12315                                 break;
12316                         case BIH_COLLISIONTRIANGLE:
12317                                 triangleindex = bihleaf->itemindex;
12318                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12319                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12320                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12321                                 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);
12322                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12323                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12324                                 break;
12325                         case BIH_RENDERTRIANGLE:
12326                                 triangleindex = bihleaf->itemindex;
12327                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12328                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12329                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12330                                 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);
12331                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12332                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12333                                 break;
12334                         }
12335                 }
12336         }
12337
12338         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12339
12340 #ifndef USE_GLES2
12341         if (r_showtris.integer && qglPolygonMode)
12342         {
12343                 if (r_showdisabledepthtest.integer)
12344                 {
12345                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12346                         GL_DepthMask(false);
12347                 }
12348                 else
12349                 {
12350                         GL_BlendFunc(GL_ONE, GL_ZERO);
12351                         GL_DepthMask(true);
12352                 }
12353                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12354                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12355                 {
12356                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12357                                 continue;
12358                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12359                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12360                         {
12361                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12362                                 if (!rsurface.texture->currentlayers->depthmask)
12363                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12364                                 else if (ent == r_refdef.scene.worldentity)
12365                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12366                                 else
12367                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12368                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12369                                 RSurf_DrawBatch();
12370                         }
12371                 }
12372                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12373                 rsurface.texture = NULL;
12374         }
12375
12376         if (r_shownormals.value != 0 && qglBegin)
12377         {
12378                 int l, k;
12379                 vec3_t v;
12380                 if (r_showdisabledepthtest.integer)
12381                 {
12382                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12383                         GL_DepthMask(false);
12384                 }
12385                 else
12386                 {
12387                         GL_BlendFunc(GL_ONE, GL_ZERO);
12388                         GL_DepthMask(true);
12389                 }
12390                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12391                 {
12392                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12393                                 continue;
12394                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12395                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12396                         {
12397                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12398                                 qglBegin(GL_LINES);
12399                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12400                                 {
12401                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12402                                         {
12403                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12404                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12405                                                 qglVertex3f(v[0], v[1], v[2]);
12406                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12407                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12408                                                 qglVertex3f(v[0], v[1], v[2]);
12409                                         }
12410                                 }
12411                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12412                                 {
12413                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12414                                         {
12415                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12416                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12417                                                 qglVertex3f(v[0], v[1], v[2]);
12418                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12419                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12420                                                 qglVertex3f(v[0], v[1], v[2]);
12421                                         }
12422                                 }
12423                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12424                                 {
12425                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12426                                         {
12427                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12428                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12429                                                 qglVertex3f(v[0], v[1], v[2]);
12430                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12431                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12432                                                 qglVertex3f(v[0], v[1], v[2]);
12433                                         }
12434                                 }
12435                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12436                                 {
12437                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12438                                         {
12439                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12440                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12441                                                 qglVertex3f(v[0], v[1], v[2]);
12442                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12443                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12444                                                 qglVertex3f(v[0], v[1], v[2]);
12445                                         }
12446                                 }
12447                                 qglEnd();
12448                                 CHECKGLERROR
12449                         }
12450                 }
12451                 rsurface.texture = NULL;
12452         }
12453 #endif
12454 }
12455
12456 int r_maxsurfacelist = 0;
12457 const msurface_t **r_surfacelist = NULL;
12458 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12459 {
12460         int i, j, endj, flagsmask;
12461         dp_model_t *model = r_refdef.scene.worldmodel;
12462         msurface_t *surfaces;
12463         unsigned char *update;
12464         int numsurfacelist = 0;
12465         if (model == NULL)
12466                 return;
12467
12468         if (r_maxsurfacelist < model->num_surfaces)
12469         {
12470                 r_maxsurfacelist = model->num_surfaces;
12471                 if (r_surfacelist)
12472                         Mem_Free((msurface_t**)r_surfacelist);
12473                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12474         }
12475
12476         RSurf_ActiveWorldEntity();
12477
12478         surfaces = model->data_surfaces;
12479         update = model->brushq1.lightmapupdateflags;
12480
12481         // update light styles on this submodel
12482         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12483         {
12484                 model_brush_lightstyleinfo_t *style;
12485                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12486                 {
12487                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12488                         {
12489                                 int *list = style->surfacelist;
12490                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12491                                 for (j = 0;j < style->numsurfaces;j++)
12492                                         update[list[j]] = true;
12493                         }
12494                 }
12495         }
12496
12497         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12498
12499         if (debug)
12500         {
12501                 R_DrawDebugModel();
12502                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12503                 return;
12504         }
12505
12506         rsurface.lightmaptexture = NULL;
12507         rsurface.deluxemaptexture = NULL;
12508         rsurface.uselightmaptexture = false;
12509         rsurface.texture = NULL;
12510         rsurface.rtlight = NULL;
12511         numsurfacelist = 0;
12512         // add visible surfaces to draw list
12513         for (i = 0;i < model->nummodelsurfaces;i++)
12514         {
12515                 j = model->sortedmodelsurfaces[i];
12516                 if (r_refdef.viewcache.world_surfacevisible[j])
12517                         r_surfacelist[numsurfacelist++] = surfaces + j;
12518         }
12519         // update lightmaps if needed
12520         if (model->brushq1.firstrender)
12521         {
12522                 model->brushq1.firstrender = false;
12523                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12524                         if (update[j])
12525                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12526         }
12527         else if (update)
12528         {
12529                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12530                         if (r_refdef.viewcache.world_surfacevisible[j])
12531                                 if (update[j])
12532                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12533         }
12534         // don't do anything if there were no surfaces
12535         if (!numsurfacelist)
12536         {
12537                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12538                 return;
12539         }
12540         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12541
12542         // add to stats if desired
12543         if (r_speeds.integer && !skysurfaces && !depthonly)
12544         {
12545                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12546                 for (j = 0;j < numsurfacelist;j++)
12547                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12548         }
12549
12550         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12551 }
12552
12553 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12554 {
12555         int i, j, endj, flagsmask;
12556         dp_model_t *model = ent->model;
12557         msurface_t *surfaces;
12558         unsigned char *update;
12559         int numsurfacelist = 0;
12560         if (model == NULL)
12561                 return;
12562
12563         if (r_maxsurfacelist < model->num_surfaces)
12564         {
12565                 r_maxsurfacelist = model->num_surfaces;
12566                 if (r_surfacelist)
12567                         Mem_Free((msurface_t **)r_surfacelist);
12568                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12569         }
12570
12571         // if the model is static it doesn't matter what value we give for
12572         // wantnormals and wanttangents, so this logic uses only rules applicable
12573         // to a model, knowing that they are meaningless otherwise
12574         if (ent == r_refdef.scene.worldentity)
12575                 RSurf_ActiveWorldEntity();
12576         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12577                 RSurf_ActiveModelEntity(ent, false, false, false);
12578         else if (prepass)
12579                 RSurf_ActiveModelEntity(ent, true, true, true);
12580         else if (depthonly)
12581         {
12582                 switch (vid.renderpath)
12583                 {
12584                 case RENDERPATH_GL20:
12585                 case RENDERPATH_D3D9:
12586                 case RENDERPATH_D3D10:
12587                 case RENDERPATH_D3D11:
12588                 case RENDERPATH_SOFT:
12589                 case RENDERPATH_GLES2:
12590                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12591                         break;
12592                 case RENDERPATH_GL11:
12593                 case RENDERPATH_GL13:
12594                 case RENDERPATH_GLES1:
12595                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12596                         break;
12597                 }
12598         }
12599         else
12600         {
12601                 switch (vid.renderpath)
12602                 {
12603                 case RENDERPATH_GL20:
12604                 case RENDERPATH_D3D9:
12605                 case RENDERPATH_D3D10:
12606                 case RENDERPATH_D3D11:
12607                 case RENDERPATH_SOFT:
12608                 case RENDERPATH_GLES2:
12609                         RSurf_ActiveModelEntity(ent, true, true, false);
12610                         break;
12611                 case RENDERPATH_GL11:
12612                 case RENDERPATH_GL13:
12613                 case RENDERPATH_GLES1:
12614                         RSurf_ActiveModelEntity(ent, true, false, false);
12615                         break;
12616                 }
12617         }
12618
12619         surfaces = model->data_surfaces;
12620         update = model->brushq1.lightmapupdateflags;
12621
12622         // update light styles
12623         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12624         {
12625                 model_brush_lightstyleinfo_t *style;
12626                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12627                 {
12628                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12629                         {
12630                                 int *list = style->surfacelist;
12631                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12632                                 for (j = 0;j < style->numsurfaces;j++)
12633                                         update[list[j]] = true;
12634                         }
12635                 }
12636         }
12637
12638         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12639
12640         if (debug)
12641         {
12642                 R_DrawDebugModel();
12643                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12644                 return;
12645         }
12646
12647         rsurface.lightmaptexture = NULL;
12648         rsurface.deluxemaptexture = NULL;
12649         rsurface.uselightmaptexture = false;
12650         rsurface.texture = NULL;
12651         rsurface.rtlight = NULL;
12652         numsurfacelist = 0;
12653         // add visible surfaces to draw list
12654         for (i = 0;i < model->nummodelsurfaces;i++)
12655                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12656         // don't do anything if there were no surfaces
12657         if (!numsurfacelist)
12658         {
12659                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12660                 return;
12661         }
12662         // update lightmaps if needed
12663         if (update)
12664         {
12665                 int updated = 0;
12666                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12667                 {
12668                         if (update[j])
12669                         {
12670                                 updated++;
12671                                 R_BuildLightMap(ent, surfaces + j);
12672                         }
12673                 }
12674         }
12675
12676         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12677
12678         // add to stats if desired
12679         if (r_speeds.integer && !skysurfaces && !depthonly)
12680         {
12681                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12682                 for (j = 0;j < numsurfacelist;j++)
12683                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12684         }
12685
12686         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12687 }
12688
12689 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12690 {
12691         static texture_t texture;
12692         static msurface_t surface;
12693         const msurface_t *surfacelist = &surface;
12694
12695         // fake enough texture and surface state to render this geometry
12696
12697         texture.update_lastrenderframe = -1; // regenerate this texture
12698         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12699         texture.currentskinframe = skinframe;
12700         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12701         texture.offsetmapping = OFFSETMAPPING_OFF;
12702         texture.offsetscale = 1;
12703         texture.specularscalemod = 1;
12704         texture.specularpowermod = 1;
12705         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12706         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12707         // JUST GREP FOR "specularscalemod = 1".
12708
12709         surface.texture = &texture;
12710         surface.num_triangles = numtriangles;
12711         surface.num_firsttriangle = firsttriangle;
12712         surface.num_vertices = numvertices;
12713         surface.num_firstvertex = firstvertex;
12714
12715         // now render it
12716         rsurface.texture = R_GetCurrentTexture(surface.texture);
12717         rsurface.lightmaptexture = NULL;
12718         rsurface.deluxemaptexture = NULL;
12719         rsurface.uselightmaptexture = false;
12720         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12721 }
12722
12723 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)
12724 {
12725         static msurface_t surface;
12726         const msurface_t *surfacelist = &surface;
12727
12728         // fake enough texture and surface state to render this geometry
12729         surface.texture = texture;
12730         surface.num_triangles = numtriangles;
12731         surface.num_firsttriangle = firsttriangle;
12732         surface.num_vertices = numvertices;
12733         surface.num_firstvertex = firstvertex;
12734
12735         // now render it
12736         rsurface.texture = R_GetCurrentTexture(surface.texture);
12737         rsurface.lightmaptexture = NULL;
12738         rsurface.deluxemaptexture = NULL;
12739         rsurface.uselightmaptexture = false;
12740         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12741 }