]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Set NvOptimusEnablement.
[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 #ifdef WIN32
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
39 extern "C" {
40 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
41 }
42 #endif
43
44 mempool_t *r_main_mempool;
45 rtexturepool_t *r_main_texturepool;
46
47 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
48
49 static qboolean r_loadnormalmap;
50 static qboolean r_loadgloss;
51 qboolean r_loadfog;
52 static qboolean r_loaddds;
53 static qboolean r_savedds;
54 static qboolean r_gpuskeletal;
55
56 //
57 // screen size info
58 //
59 r_refdef_t r_refdef;
60
61 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!"};
62 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!"};
63 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
64 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
65 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)"};
66 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
67 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"};
68 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"};
69 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"};
70 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"};
71 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"};
72 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"};
73
74 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
75 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"};
76 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
77 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)"};
78 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
79
80 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"};
81 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
82 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
83 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
84 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
85 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
86 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
87 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"};
88 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"};
89 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"};
90 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
91 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
92 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)"};
93 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
94 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
95 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"};
96 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"};
97 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
98 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"};
99 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"};
100 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"};
101 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
102 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
103 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
104 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
105 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
106 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
107 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
108 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)"};
109 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)"};
110 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
111 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
112 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
113 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
114 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
115
116 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
117 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
118 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
119
120 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
121 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
122 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
123 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."};
124 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
125 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
126 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
127 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."};
128 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
129 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
130 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
131 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."};
132 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
133 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"};
134 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"};
135 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
136 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
137 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
138 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
139 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
140 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"};
141 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
142 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
143 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
144 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
145 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
146
147 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
148 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
149 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
150 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
151 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
152 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
153 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
154 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
155
156 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)"};
157 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"};
158
159 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
160 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
161 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
162
163 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"};
164 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"};
165 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"};
166 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
167 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
168 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"};
169 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)"};
170 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)"};
171 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
172
173 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
174 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)"};
175 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
176 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)"};
177 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
178 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)"};
179 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)"};
180 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
181 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"};
182 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."};
183 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
184 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)"};
185 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)"};
186 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)"};
187 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)"};
188 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)"};
189 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)"};
190 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)"};
191 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)"};
192
193 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)"};
194 cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"};
195 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
196 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"};
197 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
198 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
199 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
200 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"};
201 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"};
202 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)"};
203
204 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
205 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
206 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
207 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
208
209 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
210 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
211
212 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
213 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
214 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
215 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
216 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
217 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
218
219 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
220 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
221 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
222 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
223 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
224 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
225 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
226 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
227 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
228 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
229
230 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"};
231
232 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"};
233
234 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
235
236 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
237
238 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)"};
239 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)"};
240 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
241 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
242
243 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
244 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"};
245
246 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."};
247
248 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)"};
249 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
250 {
251         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
252         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
253         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
254         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
255 };
256
257 extern cvar_t v_glslgamma;
258 extern cvar_t v_glslgamma_2d;
259
260 extern qboolean v_flipped_state;
261
262 r_framebufferstate_t r_fb;
263
264 /// shadow volume bsp struct with automatically growing nodes buffer
265 svbsp_t r_svbsp;
266
267 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
268
269 rtexture_t *r_texture_blanknormalmap;
270 rtexture_t *r_texture_white;
271 rtexture_t *r_texture_grey128;
272 rtexture_t *r_texture_black;
273 rtexture_t *r_texture_notexture;
274 rtexture_t *r_texture_whitecube;
275 rtexture_t *r_texture_normalizationcube;
276 rtexture_t *r_texture_fogattenuation;
277 rtexture_t *r_texture_fogheighttexture;
278 rtexture_t *r_texture_gammaramps;
279 unsigned int r_texture_gammaramps_serial;
280 //rtexture_t *r_texture_fogintensity;
281 rtexture_t *r_texture_reflectcube;
282
283 // TODO: hash lookups?
284 typedef struct cubemapinfo_s
285 {
286         char basename[64];
287         rtexture_t *texture;
288 }
289 cubemapinfo_t;
290
291 int r_texture_numcubemaps;
292 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
293
294 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
295 unsigned int r_numqueries;
296 unsigned int r_maxqueries;
297
298 typedef struct r_qwskincache_s
299 {
300         char name[MAX_QPATH];
301         skinframe_t *skinframe;
302 }
303 r_qwskincache_t;
304
305 static r_qwskincache_t *r_qwskincache;
306 static int r_qwskincache_size;
307
308 /// vertex coordinates for a quad that covers the screen exactly
309 extern const float r_screenvertex3f[12];
310 extern const float r_d3dscreenvertex3f[12];
311 const float r_screenvertex3f[12] =
312 {
313         0, 0, 0,
314         1, 0, 0,
315         1, 1, 0,
316         0, 1, 0
317 };
318 const float r_d3dscreenvertex3f[12] =
319 {
320         0, 1, 0,
321         1, 1, 0,
322         1, 0, 0,
323         0, 0, 0
324 };
325
326 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
327 {
328         int i;
329         for (i = 0;i < verts;i++)
330         {
331                 out[0] = in[0] * r;
332                 out[1] = in[1] * g;
333                 out[2] = in[2] * b;
334                 out[3] = in[3];
335                 in += 4;
336                 out += 4;
337         }
338 }
339
340 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
341 {
342         int i;
343         for (i = 0;i < verts;i++)
344         {
345                 out[0] = r;
346                 out[1] = g;
347                 out[2] = b;
348                 out[3] = a;
349                 out += 4;
350         }
351 }
352
353 // FIXME: move this to client?
354 void FOG_clear(void)
355 {
356         if (gamemode == GAME_NEHAHRA)
357         {
358                 Cvar_Set("gl_fogenable", "0");
359                 Cvar_Set("gl_fogdensity", "0.2");
360                 Cvar_Set("gl_fogred", "0.3");
361                 Cvar_Set("gl_foggreen", "0.3");
362                 Cvar_Set("gl_fogblue", "0.3");
363         }
364         r_refdef.fog_density = 0;
365         r_refdef.fog_red = 0;
366         r_refdef.fog_green = 0;
367         r_refdef.fog_blue = 0;
368         r_refdef.fog_alpha = 1;
369         r_refdef.fog_start = 0;
370         r_refdef.fog_end = 16384;
371         r_refdef.fog_height = 1<<30;
372         r_refdef.fog_fadedepth = 128;
373         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
374 }
375
376 static void R_BuildBlankTextures(void)
377 {
378         unsigned char data[4];
379         data[2] = 128; // normal X
380         data[1] = 128; // normal Y
381         data[0] = 255; // normal Z
382         data[3] = 255; // height
383         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384         data[0] = 255;
385         data[1] = 255;
386         data[2] = 255;
387         data[3] = 255;
388         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
389         data[0] = 128;
390         data[1] = 128;
391         data[2] = 128;
392         data[3] = 255;
393         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394         data[0] = 0;
395         data[1] = 0;
396         data[2] = 0;
397         data[3] = 255;
398         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
399 }
400
401 static void R_BuildNoTexture(void)
402 {
403         int x, y;
404         unsigned char pix[16][16][4];
405         // this makes a light grey/dark grey checkerboard texture
406         for (y = 0;y < 16;y++)
407         {
408                 for (x = 0;x < 16;x++)
409                 {
410                         if ((y < 8) ^ (x < 8))
411                         {
412                                 pix[y][x][0] = 128;
413                                 pix[y][x][1] = 128;
414                                 pix[y][x][2] = 128;
415                                 pix[y][x][3] = 255;
416                         }
417                         else
418                         {
419                                 pix[y][x][0] = 64;
420                                 pix[y][x][1] = 64;
421                                 pix[y][x][2] = 64;
422                                 pix[y][x][3] = 255;
423                         }
424                 }
425         }
426         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
427 }
428
429 static void R_BuildWhiteCube(void)
430 {
431         unsigned char data[6*1*1*4];
432         memset(data, 255, sizeof(data));
433         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
434 }
435
436 static void R_BuildNormalizationCube(void)
437 {
438         int x, y, side;
439         vec3_t v;
440         vec_t s, t, intensity;
441 #define NORMSIZE 64
442         unsigned char *data;
443         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
444         for (side = 0;side < 6;side++)
445         {
446                 for (y = 0;y < NORMSIZE;y++)
447                 {
448                         for (x = 0;x < NORMSIZE;x++)
449                         {
450                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
451                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
452                                 switch(side)
453                                 {
454                                 default:
455                                 case 0:
456                                         v[0] = 1;
457                                         v[1] = -t;
458                                         v[2] = -s;
459                                         break;
460                                 case 1:
461                                         v[0] = -1;
462                                         v[1] = -t;
463                                         v[2] = s;
464                                         break;
465                                 case 2:
466                                         v[0] = s;
467                                         v[1] = 1;
468                                         v[2] = t;
469                                         break;
470                                 case 3:
471                                         v[0] = s;
472                                         v[1] = -1;
473                                         v[2] = -t;
474                                         break;
475                                 case 4:
476                                         v[0] = s;
477                                         v[1] = -t;
478                                         v[2] = 1;
479                                         break;
480                                 case 5:
481                                         v[0] = -s;
482                                         v[1] = -t;
483                                         v[2] = -1;
484                                         break;
485                                 }
486                                 intensity = 127.0f / sqrt(DotProduct(v, v));
487                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
488                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
489                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
490                                 data[((side*64+y)*64+x)*4+3] = 255;
491                         }
492                 }
493         }
494         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
495         Mem_Free(data);
496 }
497
498 static void R_BuildFogTexture(void)
499 {
500         int x, b;
501 #define FOGWIDTH 256
502         unsigned char data1[FOGWIDTH][4];
503         //unsigned char data2[FOGWIDTH][4];
504         double d, r, alpha;
505
506         r_refdef.fogmasktable_start = r_refdef.fog_start;
507         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
508         r_refdef.fogmasktable_range = r_refdef.fogrange;
509         r_refdef.fogmasktable_density = r_refdef.fog_density;
510
511         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
512         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
513         {
514                 d = (x * r - r_refdef.fogmasktable_start);
515                 if(developer_extra.integer)
516                         Con_DPrintf("%f ", d);
517                 d = max(0, d);
518                 if (r_fog_exp2.integer)
519                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
520                 else
521                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
522                 if(developer_extra.integer)
523                         Con_DPrintf(" : %f ", alpha);
524                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
525                 if(developer_extra.integer)
526                         Con_DPrintf(" = %f\n", alpha);
527                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
528         }
529
530         for (x = 0;x < FOGWIDTH;x++)
531         {
532                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
533                 data1[x][0] = b;
534                 data1[x][1] = b;
535                 data1[x][2] = b;
536                 data1[x][3] = 255;
537                 //data2[x][0] = 255 - b;
538                 //data2[x][1] = 255 - b;
539                 //data2[x][2] = 255 - b;
540                 //data2[x][3] = 255;
541         }
542         if (r_texture_fogattenuation)
543         {
544                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
545                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
546         }
547         else
548         {
549                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
550                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
551         }
552 }
553
554 static void R_BuildFogHeightTexture(void)
555 {
556         unsigned char *inpixels;
557         int size;
558         int x;
559         int y;
560         int j;
561         float c[4];
562         float f;
563         inpixels = NULL;
564         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
565         if (r_refdef.fogheighttexturename[0])
566                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
567         if (!inpixels)
568         {
569                 r_refdef.fog_height_tablesize = 0;
570                 if (r_texture_fogheighttexture)
571                         R_FreeTexture(r_texture_fogheighttexture);
572                 r_texture_fogheighttexture = NULL;
573                 if (r_refdef.fog_height_table2d)
574                         Mem_Free(r_refdef.fog_height_table2d);
575                 r_refdef.fog_height_table2d = NULL;
576                 if (r_refdef.fog_height_table1d)
577                         Mem_Free(r_refdef.fog_height_table1d);
578                 r_refdef.fog_height_table1d = NULL;
579                 return;
580         }
581         size = image_width;
582         r_refdef.fog_height_tablesize = size;
583         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
584         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
585         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
586         Mem_Free(inpixels);
587         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
588         // average fog color table accounting for every fog layer between a point
589         // and the camera.  (Note: attenuation is handled separately!)
590         for (y = 0;y < size;y++)
591         {
592                 for (x = 0;x < size;x++)
593                 {
594                         Vector4Clear(c);
595                         f = 0;
596                         if (x < y)
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                         else
605                         {
606                                 for (j = x;j >= y;j--)
607                                 {
608                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
609                                         f++;
610                                 }
611                         }
612                         f = 1.0f / f;
613                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
614                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
615                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
616                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
617                 }
618         }
619         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
620 }
621
622 //=======================================================================================================================================================
623
624 static const char *builtinshaderstrings[] =
625 {
626 #include "shader_glsl.h"
627 0
628 };
629
630 const char *builtinhlslshaderstrings[] =
631 {
632 #include "shader_hlsl.h"
633 0
634 };
635
636 char *glslshaderstring = NULL;
637 char *hlslshaderstring = NULL;
638
639 //=======================================================================================================================================================
640
641 typedef struct shaderpermutationinfo_s
642 {
643         const char *pretext;
644         const char *name;
645 }
646 shaderpermutationinfo_t;
647
648 typedef struct shadermodeinfo_s
649 {
650         const char *filename;
651         const char *pretext;
652         const char *name;
653 }
654 shadermodeinfo_t;
655
656 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
657 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
658 {
659         {"#define USEDIFFUSE\n", " diffuse"},
660         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
661         {"#define USEVIEWTINT\n", " viewtint"},
662         {"#define USECOLORMAPPING\n", " colormapping"},
663         {"#define USESATURATION\n", " saturation"},
664         {"#define USEFOGINSIDE\n", " foginside"},
665         {"#define USEFOGOUTSIDE\n", " fogoutside"},
666         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
667         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
668         {"#define USEGAMMARAMPS\n", " gammaramps"},
669         {"#define USECUBEFILTER\n", " cubefilter"},
670         {"#define USEGLOW\n", " glow"},
671         {"#define USEBLOOM\n", " bloom"},
672         {"#define USESPECULAR\n", " specular"},
673         {"#define USEPOSTPROCESSING\n", " postprocessing"},
674         {"#define USEREFLECTION\n", " reflection"},
675         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
676         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
677         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
678         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
679         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
680         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
681         {"#define USEALPHAKILL\n", " alphakill"},
682         {"#define USEREFLECTCUBE\n", " reflectcube"},
683         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
684         {"#define USEBOUNCEGRID\n", " bouncegrid"},
685         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
686         {"#define USETRIPPY\n", " trippy"},
687         {"#define USEDEPTHRGB\n", " depthrgb"},
688         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
689         {"#define USESKELETAL\n", " skeletal"},
690         {"#define USEOCCLUDE\n", " occlude"}
691 };
692
693 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
694 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
695 {
696         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
697         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
698         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
699         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
700         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
701         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
702         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
703         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
704         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
705         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
706         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
707         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
710         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
711         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
712         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
713 };
714
715 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
716 {
717         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
718         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
719         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
720         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
721         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
722         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
723         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
724         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
725         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
726         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
727         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
728         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
729         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
730         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
731         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
732         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
733         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
734 };
735
736 struct r_glsl_permutation_s;
737 typedef struct r_glsl_permutation_s
738 {
739         /// hash lookup data
740         struct r_glsl_permutation_s *hashnext;
741         unsigned int mode;
742         unsigned int permutation;
743
744         /// indicates if we have tried compiling this permutation already
745         qboolean compiled;
746         /// 0 if compilation failed
747         int program;
748         // texture units assigned to each detected uniform
749         int tex_Texture_First;
750         int tex_Texture_Second;
751         int tex_Texture_GammaRamps;
752         int tex_Texture_Normal;
753         int tex_Texture_Color;
754         int tex_Texture_Gloss;
755         int tex_Texture_Glow;
756         int tex_Texture_SecondaryNormal;
757         int tex_Texture_SecondaryColor;
758         int tex_Texture_SecondaryGloss;
759         int tex_Texture_SecondaryGlow;
760         int tex_Texture_Pants;
761         int tex_Texture_Shirt;
762         int tex_Texture_FogHeightTexture;
763         int tex_Texture_FogMask;
764         int tex_Texture_Lightmap;
765         int tex_Texture_Deluxemap;
766         int tex_Texture_Attenuation;
767         int tex_Texture_Cube;
768         int tex_Texture_Refraction;
769         int tex_Texture_Reflection;
770         int tex_Texture_ShadowMap2D;
771         int tex_Texture_CubeProjection;
772         int tex_Texture_ScreenNormalMap;
773         int tex_Texture_ScreenDiffuse;
774         int tex_Texture_ScreenSpecular;
775         int tex_Texture_ReflectMask;
776         int tex_Texture_ReflectCube;
777         int tex_Texture_BounceGrid;
778         /// locations of detected uniforms in program object, or -1 if not found
779         int loc_Texture_First;
780         int loc_Texture_Second;
781         int loc_Texture_GammaRamps;
782         int loc_Texture_Normal;
783         int loc_Texture_Color;
784         int loc_Texture_Gloss;
785         int loc_Texture_Glow;
786         int loc_Texture_SecondaryNormal;
787         int loc_Texture_SecondaryColor;
788         int loc_Texture_SecondaryGloss;
789         int loc_Texture_SecondaryGlow;
790         int loc_Texture_Pants;
791         int loc_Texture_Shirt;
792         int loc_Texture_FogHeightTexture;
793         int loc_Texture_FogMask;
794         int loc_Texture_Lightmap;
795         int loc_Texture_Deluxemap;
796         int loc_Texture_Attenuation;
797         int loc_Texture_Cube;
798         int loc_Texture_Refraction;
799         int loc_Texture_Reflection;
800         int loc_Texture_ShadowMap2D;
801         int loc_Texture_CubeProjection;
802         int loc_Texture_ScreenNormalMap;
803         int loc_Texture_ScreenDiffuse;
804         int loc_Texture_ScreenSpecular;
805         int loc_Texture_ReflectMask;
806         int loc_Texture_ReflectCube;
807         int loc_Texture_BounceGrid;
808         int loc_Alpha;
809         int loc_BloomBlur_Parameters;
810         int loc_ClientTime;
811         int loc_Color_Ambient;
812         int loc_Color_Diffuse;
813         int loc_Color_Specular;
814         int loc_Color_Glow;
815         int loc_Color_Pants;
816         int loc_Color_Shirt;
817         int loc_DeferredColor_Ambient;
818         int loc_DeferredColor_Diffuse;
819         int loc_DeferredColor_Specular;
820         int loc_DeferredMod_Diffuse;
821         int loc_DeferredMod_Specular;
822         int loc_DistortScaleRefractReflect;
823         int loc_EyePosition;
824         int loc_FogColor;
825         int loc_FogHeightFade;
826         int loc_FogPlane;
827         int loc_FogPlaneViewDist;
828         int loc_FogRangeRecip;
829         int loc_LightColor;
830         int loc_LightDir;
831         int loc_LightPosition;
832         int loc_OffsetMapping_ScaleSteps;
833         int loc_OffsetMapping_LodDistance;
834         int loc_OffsetMapping_Bias;
835         int loc_PixelSize;
836         int loc_ReflectColor;
837         int loc_ReflectFactor;
838         int loc_ReflectOffset;
839         int loc_RefractColor;
840         int loc_Saturation;
841         int loc_ScreenCenterRefractReflect;
842         int loc_ScreenScaleRefractReflect;
843         int loc_ScreenToDepth;
844         int loc_ShadowMap_Parameters;
845         int loc_ShadowMap_TextureScale;
846         int loc_SpecularPower;
847         int loc_Skeletal_Transform12;
848         int loc_UserVec1;
849         int loc_UserVec2;
850         int loc_UserVec3;
851         int loc_UserVec4;
852         int loc_ViewTintColor;
853         int loc_ViewToLight;
854         int loc_ModelToLight;
855         int loc_TexMatrix;
856         int loc_BackgroundTexMatrix;
857         int loc_ModelViewProjectionMatrix;
858         int loc_ModelViewMatrix;
859         int loc_PixelToScreenTexCoord;
860         int loc_ModelToReflectCube;
861         int loc_ShadowMapMatrix;
862         int loc_BloomColorSubtract;
863         int loc_NormalmapScrollBlend;
864         int loc_BounceGridMatrix;
865         int loc_BounceGridIntensity;
866         /// uniform block bindings
867         int ubibind_Skeletal_Transform12_UniformBlock;
868         /// uniform block indices
869         int ubiloc_Skeletal_Transform12_UniformBlock;
870 }
871 r_glsl_permutation_t;
872
873 #define SHADERPERMUTATION_HASHSIZE 256
874
875
876 // non-degradable "lightweight" shader parameters to keep the permutations simpler
877 // these can NOT degrade! only use for simple stuff
878 enum
879 {
880         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
881         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
882         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
883         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
884         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
885         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
886         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
887         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
888         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
889         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
890         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
891         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
892         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
893         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
894 };
895 #define SHADERSTATICPARMS_COUNT 14
896
897 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
898 static int shaderstaticparms_count = 0;
899
900 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
901 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
902
903 extern qboolean r_shadow_shadowmapsampler;
904 extern int r_shadow_shadowmappcf;
905 qboolean R_CompileShader_CheckStaticParms(void)
906 {
907         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
908         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
909         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
910
911         // detect all
912         if (r_glsl_saturation_redcompensate.integer)
913                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
914         if (r_glsl_vertextextureblend_usebothalphas.integer)
915                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
916         if (r_shadow_glossexact.integer)
917                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
918         if (r_glsl_postprocess.integer)
919         {
920                 if (r_glsl_postprocess_uservec1_enable.integer)
921                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
922                 if (r_glsl_postprocess_uservec2_enable.integer)
923                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
924                 if (r_glsl_postprocess_uservec3_enable.integer)
925                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
926                 if (r_glsl_postprocess_uservec4_enable.integer)
927                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
928         }
929         if (r_fxaa.integer)
930                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
931         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
932                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
933
934         if (r_shadow_shadowmapsampler)
935                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
936         if (r_shadow_shadowmappcf > 1)
937                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
938         else if (r_shadow_shadowmappcf)
939                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
940         if (r_celshading.integer)
941                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
942         if (r_celoutlines.integer)
943                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
944
945         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
946 }
947
948 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
949         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
950                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
951         else \
952                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
953 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
954 {
955         shaderstaticparms_count = 0;
956
957         // emit all
958         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
959         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
960         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
961         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
962         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
963         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
964         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
965         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
966         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
967         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
968         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
969         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
972 }
973
974 /// information about each possible shader permutation
975 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
976 /// currently selected permutation
977 r_glsl_permutation_t *r_glsl_permutation;
978 /// storage for permutations linked in the hash table
979 memexpandablearray_t r_glsl_permutationarray;
980
981 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
982 {
983         //unsigned int hashdepth = 0;
984         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
985         r_glsl_permutation_t *p;
986         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
987         {
988                 if (p->mode == mode && p->permutation == permutation)
989                 {
990                         //if (hashdepth > 10)
991                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
992                         return p;
993                 }
994                 //hashdepth++;
995         }
996         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
997         p->mode = mode;
998         p->permutation = permutation;
999         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1000         r_glsl_permutationhash[mode][hashindex] = p;
1001         //if (hashdepth > 10)
1002         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1003         return p;
1004 }
1005
1006 static char *R_ShaderStrCat(const char **strings)
1007 {
1008         char *string, *s;
1009         const char **p = strings;
1010         const char *t;
1011         size_t len = 0;
1012         for (p = strings;(t = *p);p++)
1013                 len += strlen(t);
1014         len++;
1015         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1016         len = 0;
1017         for (p = strings;(t = *p);p++)
1018         {
1019                 len = strlen(t);
1020                 memcpy(s, t, len);
1021                 s += len;
1022         }
1023         *s = 0;
1024         return string;
1025 }
1026
1027 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1028 {
1029         char *shaderstring;
1030         if (!filename || !filename[0])
1031                 return NULL;
1032         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1033         if (!strcmp(filename, "glsl/default.glsl"))
1034         {
1035                 if (builtinonly)
1036                         return R_ShaderStrCat(builtinshaderstrings);
1037                 if (!glslshaderstring)
1038                 {
1039                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1040                         if (glslshaderstring)
1041                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1042                         else
1043                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1044                 }
1045                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1046                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1047                 return shaderstring;
1048         }
1049         if (!strcmp(filename, "hlsl/default.hlsl"))
1050         {
1051                 if (builtinonly)
1052                         return R_ShaderStrCat(builtinhlslshaderstrings);
1053                 if (!hlslshaderstring)
1054                 {
1055                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1056                         if (hlslshaderstring)
1057                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1058                         else
1059                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1060                 }
1061                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1062                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1063                 return shaderstring;
1064         }
1065         // we don't have builtin strings for any other files
1066         if (builtinonly)
1067                 return NULL;
1068         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1069         if (shaderstring)
1070         {
1071                 if (printfromdisknotice)
1072                         Con_DPrintf("from disk %s... ", filename);
1073                 return shaderstring;
1074         }
1075         return shaderstring;
1076 }
1077
1078 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1079 {
1080         int i;
1081         int ubibind;
1082         int sampler;
1083         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1084         char *sourcestring;
1085         char permutationname[256];
1086         int vertstrings_count = 0;
1087         int geomstrings_count = 0;
1088         int fragstrings_count = 0;
1089         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1090         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1091         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1092
1093         if (p->compiled)
1094                 return;
1095         p->compiled = true;
1096         p->program = 0;
1097
1098         permutationname[0] = 0;
1099         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1100
1101         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1102
1103         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1104         if(vid.support.glshaderversion >= 140)
1105         {
1106                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1107                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1108                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1109                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1110                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1111                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1112         }
1113         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1114         else if(vid.support.glshaderversion >= 130)
1115         {
1116                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1117                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1118                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1119                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1120                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1121                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1122         }
1123
1124         // the first pretext is which type of shader to compile as
1125         // (later these will all be bound together as a program object)
1126         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1127         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1128         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1129
1130         // the second pretext is the mode (for example a light source)
1131         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1132         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1133         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1134         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1135
1136         // now add all the permutation pretexts
1137         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1138         {
1139                 if (permutation & (1<<i))
1140                 {
1141                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1142                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1143                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1144                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1145                 }
1146                 else
1147                 {
1148                         // keep line numbers correct
1149                         vertstrings_list[vertstrings_count++] = "\n";
1150                         geomstrings_list[geomstrings_count++] = "\n";
1151                         fragstrings_list[fragstrings_count++] = "\n";
1152                 }
1153         }
1154
1155         // add static parms
1156         R_CompileShader_AddStaticParms(mode, permutation);
1157         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1158         vertstrings_count += shaderstaticparms_count;
1159         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1160         geomstrings_count += shaderstaticparms_count;
1161         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1162         fragstrings_count += shaderstaticparms_count;
1163
1164         // now append the shader text itself
1165         vertstrings_list[vertstrings_count++] = sourcestring;
1166         geomstrings_list[geomstrings_count++] = sourcestring;
1167         fragstrings_list[fragstrings_count++] = sourcestring;
1168
1169         // compile the shader program
1170         if (vertstrings_count + geomstrings_count + fragstrings_count)
1171                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1172         if (p->program)
1173         {
1174                 CHECKGLERROR
1175                 qglUseProgram(p->program);CHECKGLERROR
1176                 // look up all the uniform variable names we care about, so we don't
1177                 // have to look them up every time we set them
1178
1179 #if 0
1180                 // debugging aid
1181                 {
1182                         GLint activeuniformindex = 0;
1183                         GLint numactiveuniforms = 0;
1184                         char uniformname[128];
1185                         GLsizei uniformnamelength = 0;
1186                         GLint uniformsize = 0;
1187                         GLenum uniformtype = 0;
1188                         memset(uniformname, 0, sizeof(uniformname));
1189                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1190                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1191                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1192                         {
1193                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1194                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1195                         }
1196                 }
1197 #endif
1198
1199                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1200                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1201                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1202                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1203                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1204                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1205                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1206                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1207                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1208                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1209                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1210                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1211                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1212                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1213                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1214                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1215                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1216                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1217                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1218                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1219                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1220                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1221                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1222                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1223                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1224                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1225                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1226                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1227                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1228                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1229                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1230                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1231                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1232                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1233                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1234                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1235                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1236                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1237                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1238                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1239                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1240                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1241                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1242                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1243                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1244                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1245                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1246                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1247                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1248                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1249                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1250                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1251                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1252                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1253                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1254                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1255                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1256                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1257                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1258                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1259                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1260                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1261                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1262                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1263                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1264                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1265                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1266                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1267                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1268                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1269                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1270                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1271                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1272                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1273                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1274                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1275                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1276                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1277                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1278                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1279                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1280                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1281                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1282                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1283                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1284                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1285                 // initialize the samplers to refer to the texture units we use
1286                 p->tex_Texture_First = -1;
1287                 p->tex_Texture_Second = -1;
1288                 p->tex_Texture_GammaRamps = -1;
1289                 p->tex_Texture_Normal = -1;
1290                 p->tex_Texture_Color = -1;
1291                 p->tex_Texture_Gloss = -1;
1292                 p->tex_Texture_Glow = -1;
1293                 p->tex_Texture_SecondaryNormal = -1;
1294                 p->tex_Texture_SecondaryColor = -1;
1295                 p->tex_Texture_SecondaryGloss = -1;
1296                 p->tex_Texture_SecondaryGlow = -1;
1297                 p->tex_Texture_Pants = -1;
1298                 p->tex_Texture_Shirt = -1;
1299                 p->tex_Texture_FogHeightTexture = -1;
1300                 p->tex_Texture_FogMask = -1;
1301                 p->tex_Texture_Lightmap = -1;
1302                 p->tex_Texture_Deluxemap = -1;
1303                 p->tex_Texture_Attenuation = -1;
1304                 p->tex_Texture_Cube = -1;
1305                 p->tex_Texture_Refraction = -1;
1306                 p->tex_Texture_Reflection = -1;
1307                 p->tex_Texture_ShadowMap2D = -1;
1308                 p->tex_Texture_CubeProjection = -1;
1309                 p->tex_Texture_ScreenNormalMap = -1;
1310                 p->tex_Texture_ScreenDiffuse = -1;
1311                 p->tex_Texture_ScreenSpecular = -1;
1312                 p->tex_Texture_ReflectMask = -1;
1313                 p->tex_Texture_ReflectCube = -1;
1314                 p->tex_Texture_BounceGrid = -1;
1315                 // bind the texture samplers in use
1316                 sampler = 0;
1317                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1318                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1319                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1320                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1321                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1322                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1323                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1324                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1325                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1326                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1327                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1328                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1329                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1330                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1331                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1332                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1333                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1334                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1335                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1336                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1337                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1338                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1339                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1340                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1341                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1342                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1343                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1344                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1345                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1346                 // get the uniform block indices so we can bind them
1347 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1348                 if (vid.support.arb_uniform_buffer_object)
1349                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1350                 else
1351 #endif
1352                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1353                 // clear the uniform block bindings
1354                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1355                 // bind the uniform blocks in use
1356                 ubibind = 0;
1357 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1358                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1359 #endif
1360                 // we're done compiling and setting up the shader, at least until it is used
1361                 CHECKGLERROR
1362                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1363         }
1364         else
1365                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1366
1367         // free the strings
1368         if (sourcestring)
1369                 Mem_Free(sourcestring);
1370 }
1371
1372 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1373 {
1374         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1375         if (r_glsl_permutation != perm)
1376         {
1377                 r_glsl_permutation = perm;
1378                 if (!r_glsl_permutation->program)
1379                 {
1380                         if (!r_glsl_permutation->compiled)
1381                         {
1382                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1383                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1384                         }
1385                         if (!r_glsl_permutation->program)
1386                         {
1387                                 // remove features until we find a valid permutation
1388                                 int i;
1389                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1390                                 {
1391                                         // reduce i more quickly whenever it would not remove any bits
1392                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1393                                         if (!(permutation & j))
1394                                                 continue;
1395                                         permutation -= j;
1396                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1397                                         if (!r_glsl_permutation->compiled)
1398                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1399                                         if (r_glsl_permutation->program)
1400                                                 break;
1401                                 }
1402                                 if (i >= SHADERPERMUTATION_COUNT)
1403                                 {
1404                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1405                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1406                                         qglUseProgram(0);CHECKGLERROR
1407                                         return; // no bit left to clear, entire mode is broken
1408                                 }
1409                         }
1410                 }
1411                 CHECKGLERROR
1412                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1413         }
1414         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1415         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1416         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1417         CHECKGLERROR
1418 }
1419
1420 #ifdef SUPPORTD3D
1421
1422 #ifdef SUPPORTD3D
1423 #include <d3d9.h>
1424 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1425 extern D3DCAPS9 vid_d3d9caps;
1426 #endif
1427
1428 struct r_hlsl_permutation_s;
1429 typedef struct r_hlsl_permutation_s
1430 {
1431         /// hash lookup data
1432         struct r_hlsl_permutation_s *hashnext;
1433         unsigned int mode;
1434         unsigned int permutation;
1435
1436         /// indicates if we have tried compiling this permutation already
1437         qboolean compiled;
1438         /// NULL if compilation failed
1439         IDirect3DVertexShader9 *vertexshader;
1440         IDirect3DPixelShader9 *pixelshader;
1441 }
1442 r_hlsl_permutation_t;
1443
1444 typedef enum D3DVSREGISTER_e
1445 {
1446         D3DVSREGISTER_TexMatrix = 0, // float4x4
1447         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1448         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1449         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1450         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1451         D3DVSREGISTER_ModelToLight = 20, // float4x4
1452         D3DVSREGISTER_EyePosition = 24,
1453         D3DVSREGISTER_FogPlane = 25,
1454         D3DVSREGISTER_LightDir = 26,
1455         D3DVSREGISTER_LightPosition = 27,
1456 }
1457 D3DVSREGISTER_t;
1458
1459 typedef enum D3DPSREGISTER_e
1460 {
1461         D3DPSREGISTER_Alpha = 0,
1462         D3DPSREGISTER_BloomBlur_Parameters = 1,
1463         D3DPSREGISTER_ClientTime = 2,
1464         D3DPSREGISTER_Color_Ambient = 3,
1465         D3DPSREGISTER_Color_Diffuse = 4,
1466         D3DPSREGISTER_Color_Specular = 5,
1467         D3DPSREGISTER_Color_Glow = 6,
1468         D3DPSREGISTER_Color_Pants = 7,
1469         D3DPSREGISTER_Color_Shirt = 8,
1470         D3DPSREGISTER_DeferredColor_Ambient = 9,
1471         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1472         D3DPSREGISTER_DeferredColor_Specular = 11,
1473         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1474         D3DPSREGISTER_DeferredMod_Specular = 13,
1475         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1476         D3DPSREGISTER_EyePosition = 15, // unused
1477         D3DPSREGISTER_FogColor = 16,
1478         D3DPSREGISTER_FogHeightFade = 17,
1479         D3DPSREGISTER_FogPlane = 18,
1480         D3DPSREGISTER_FogPlaneViewDist = 19,
1481         D3DPSREGISTER_FogRangeRecip = 20,
1482         D3DPSREGISTER_LightColor = 21,
1483         D3DPSREGISTER_LightDir = 22, // unused
1484         D3DPSREGISTER_LightPosition = 23,
1485         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1486         D3DPSREGISTER_PixelSize = 25,
1487         D3DPSREGISTER_ReflectColor = 26,
1488         D3DPSREGISTER_ReflectFactor = 27,
1489         D3DPSREGISTER_ReflectOffset = 28,
1490         D3DPSREGISTER_RefractColor = 29,
1491         D3DPSREGISTER_Saturation = 30,
1492         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1493         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1494         D3DPSREGISTER_ScreenToDepth = 33,
1495         D3DPSREGISTER_ShadowMap_Parameters = 34,
1496         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1497         D3DPSREGISTER_SpecularPower = 36,
1498         D3DPSREGISTER_UserVec1 = 37,
1499         D3DPSREGISTER_UserVec2 = 38,
1500         D3DPSREGISTER_UserVec3 = 39,
1501         D3DPSREGISTER_UserVec4 = 40,
1502         D3DPSREGISTER_ViewTintColor = 41,
1503         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1504         D3DPSREGISTER_BloomColorSubtract = 43,
1505         D3DPSREGISTER_ViewToLight = 44, // float4x4
1506         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1507         D3DPSREGISTER_NormalmapScrollBlend = 52,
1508         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1509         D3DPSREGISTER_OffsetMapping_Bias = 54,
1510         // next at 54
1511 }
1512 D3DPSREGISTER_t;
1513
1514 /// information about each possible shader permutation
1515 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1516 /// currently selected permutation
1517 r_hlsl_permutation_t *r_hlsl_permutation;
1518 /// storage for permutations linked in the hash table
1519 memexpandablearray_t r_hlsl_permutationarray;
1520
1521 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1522 {
1523         //unsigned int hashdepth = 0;
1524         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1525         r_hlsl_permutation_t *p;
1526         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1527         {
1528                 if (p->mode == mode && p->permutation == permutation)
1529                 {
1530                         //if (hashdepth > 10)
1531                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1532                         return p;
1533                 }
1534                 //hashdepth++;
1535         }
1536         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1537         p->mode = mode;
1538         p->permutation = permutation;
1539         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1540         r_hlsl_permutationhash[mode][hashindex] = p;
1541         //if (hashdepth > 10)
1542         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1543         return p;
1544 }
1545
1546 #include <d3dx9.h>
1547 //#include <d3dx9shader.h>
1548 //#include <d3dx9mesh.h>
1549
1550 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1551 {
1552         DWORD *vsbin = NULL;
1553         DWORD *psbin = NULL;
1554         fs_offset_t vsbinsize;
1555         fs_offset_t psbinsize;
1556 //      IDirect3DVertexShader9 *vs = NULL;
1557 //      IDirect3DPixelShader9 *ps = NULL;
1558         ID3DXBuffer *vslog = NULL;
1559         ID3DXBuffer *vsbuffer = NULL;
1560         ID3DXConstantTable *vsconstanttable = NULL;
1561         ID3DXBuffer *pslog = NULL;
1562         ID3DXBuffer *psbuffer = NULL;
1563         ID3DXConstantTable *psconstanttable = NULL;
1564         int vsresult = 0;
1565         int psresult = 0;
1566         char temp[MAX_INPUTLINE];
1567         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1568         char vabuf[1024];
1569         qboolean debugshader = gl_paranoid.integer != 0;
1570         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1571         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1572         if (!debugshader)
1573         {
1574                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1575                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1576         }
1577         if ((!vsbin && vertstring) || (!psbin && fragstring))
1578         {
1579                 const char* dllnames_d3dx9 [] =
1580                 {
1581                         "d3dx9_43.dll",
1582                         "d3dx9_42.dll",
1583                         "d3dx9_41.dll",
1584                         "d3dx9_40.dll",
1585                         "d3dx9_39.dll",
1586                         "d3dx9_38.dll",
1587                         "d3dx9_37.dll",
1588                         "d3dx9_36.dll",
1589                         "d3dx9_35.dll",
1590                         "d3dx9_34.dll",
1591                         "d3dx9_33.dll",
1592                         "d3dx9_32.dll",
1593                         "d3dx9_31.dll",
1594                         "d3dx9_30.dll",
1595                         "d3dx9_29.dll",
1596                         "d3dx9_28.dll",
1597                         "d3dx9_27.dll",
1598                         "d3dx9_26.dll",
1599                         "d3dx9_25.dll",
1600                         "d3dx9_24.dll",
1601                         NULL
1602                 };
1603                 dllhandle_t d3dx9_dll = NULL;
1604                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1605                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1606                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1607                 dllfunction_t d3dx9_dllfuncs[] =
1608                 {
1609                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1610                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1611                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1612                         {NULL, NULL}
1613                 };
1614                 // 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...
1615 #ifndef ID3DXBuffer_GetBufferPointer
1616 #if !defined(__cplusplus) || defined(CINTERFACE)
1617 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1618 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1619 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1620 #else
1621 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1622 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1623 #define ID3DXBuffer_Release(p)            (p)->Release()
1624 #endif
1625 #endif
1626                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1627                 {
1628                         DWORD shaderflags = 0;
1629                         if (debugshader)
1630                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1631                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1632                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1633                         if (vertstring && vertstring[0])
1634                         {
1635                                 if (debugshader)
1636                                 {
1637                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1638                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1639                                 }
1640                                 else
1641                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1642                                 if (vsbuffer)
1643                                 {
1644                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1645                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1646                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1647                                         ID3DXBuffer_Release(vsbuffer);
1648                                 }
1649                                 if (vslog)
1650                                 {
1651                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1652                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1653                                         ID3DXBuffer_Release(vslog);
1654                                 }
1655                         }
1656                         if (fragstring && fragstring[0])
1657                         {
1658                                 if (debugshader)
1659                                 {
1660                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1661                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1662                                 }
1663                                 else
1664                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1665                                 if (psbuffer)
1666                                 {
1667                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1668                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1669                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1670                                         ID3DXBuffer_Release(psbuffer);
1671                                 }
1672                                 if (pslog)
1673                                 {
1674                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1675                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1676                                         ID3DXBuffer_Release(pslog);
1677                                 }
1678                         }
1679                         Sys_UnloadLibrary(&d3dx9_dll);
1680                 }
1681                 else
1682                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1683         }
1684         if (vsbin && psbin)
1685         {
1686                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1687                 if (FAILED(vsresult))
1688                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1689                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1690                 if (FAILED(psresult))
1691                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1692         }
1693         // free the shader data
1694         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1695         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1696 }
1697
1698 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1699 {
1700         int i;
1701         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1702         int vertstring_length = 0;
1703         int geomstring_length = 0;
1704         int fragstring_length = 0;
1705         char *t;
1706         char *sourcestring;
1707         char *vertstring, *geomstring, *fragstring;
1708         char permutationname[256];
1709         char cachename[256];
1710         int vertstrings_count = 0;
1711         int geomstrings_count = 0;
1712         int fragstrings_count = 0;
1713         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1714         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1715         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1716
1717         if (p->compiled)
1718                 return;
1719         p->compiled = true;
1720         p->vertexshader = NULL;
1721         p->pixelshader = NULL;
1722
1723         permutationname[0] = 0;
1724         cachename[0] = 0;
1725         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1726
1727         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1728         strlcat(cachename, "hlsl/", sizeof(cachename));
1729
1730         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1731         vertstrings_count = 0;
1732         geomstrings_count = 0;
1733         fragstrings_count = 0;
1734         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1735         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1736         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1737
1738         // the first pretext is which type of shader to compile as
1739         // (later these will all be bound together as a program object)
1740         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1741         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1742         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1743
1744         // the second pretext is the mode (for example a light source)
1745         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1746         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1747         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1748         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1749         strlcat(cachename, modeinfo->name, sizeof(cachename));
1750
1751         // now add all the permutation pretexts
1752         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1753         {
1754                 if (permutation & (1<<i))
1755                 {
1756                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1757                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1758                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1759                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1760                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1761                 }
1762                 else
1763                 {
1764                         // keep line numbers correct
1765                         vertstrings_list[vertstrings_count++] = "\n";
1766                         geomstrings_list[geomstrings_count++] = "\n";
1767                         fragstrings_list[fragstrings_count++] = "\n";
1768                 }
1769         }
1770
1771         // add static parms
1772         R_CompileShader_AddStaticParms(mode, permutation);
1773         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1774         vertstrings_count += shaderstaticparms_count;
1775         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1776         geomstrings_count += shaderstaticparms_count;
1777         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1778         fragstrings_count += shaderstaticparms_count;
1779
1780         // replace spaces in the cachename with _ characters
1781         for (i = 0;cachename[i];i++)
1782                 if (cachename[i] == ' ')
1783                         cachename[i] = '_';
1784
1785         // now append the shader text itself
1786         vertstrings_list[vertstrings_count++] = sourcestring;
1787         geomstrings_list[geomstrings_count++] = sourcestring;
1788         fragstrings_list[fragstrings_count++] = sourcestring;
1789
1790         vertstring_length = 0;
1791         for (i = 0;i < vertstrings_count;i++)
1792                 vertstring_length += (int)strlen(vertstrings_list[i]);
1793         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1794         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1795                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1796
1797         geomstring_length = 0;
1798         for (i = 0;i < geomstrings_count;i++)
1799                 geomstring_length += (int)strlen(geomstrings_list[i]);
1800         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1801         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1802                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1803
1804         fragstring_length = 0;
1805         for (i = 0;i < fragstrings_count;i++)
1806                 fragstring_length += (int)strlen(fragstrings_list[i]);
1807         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1808         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1809                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1810
1811         // try to load the cached shader, or generate one
1812         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1813
1814         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1815                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1816         else
1817                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1818
1819         // free the strings
1820         if (vertstring)
1821                 Mem_Free(vertstring);
1822         if (geomstring)
1823                 Mem_Free(geomstring);
1824         if (fragstring)
1825                 Mem_Free(fragstring);
1826         if (sourcestring)
1827                 Mem_Free(sourcestring);
1828 }
1829
1830 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1831 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1832 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);}
1833 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);}
1834 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);}
1835 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);}
1836
1837 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1838 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1839 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);}
1840 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);}
1841 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);}
1842 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);}
1843
1844 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1845 {
1846         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1847         if (r_hlsl_permutation != perm)
1848         {
1849                 r_hlsl_permutation = perm;
1850                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1851                 {
1852                         if (!r_hlsl_permutation->compiled)
1853                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1854                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1855                         {
1856                                 // remove features until we find a valid permutation
1857                                 int i;
1858                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1859                                 {
1860                                         // reduce i more quickly whenever it would not remove any bits
1861                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1862                                         if (!(permutation & j))
1863                                                 continue;
1864                                         permutation -= j;
1865                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1866                                         if (!r_hlsl_permutation->compiled)
1867                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1868                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1869                                                 break;
1870                                 }
1871                                 if (i >= SHADERPERMUTATION_COUNT)
1872                                 {
1873                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1874                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1875                                         return; // no bit left to clear, entire mode is broken
1876                                 }
1877                         }
1878                 }
1879                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1880                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1881         }
1882         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1883         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1884         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1885 }
1886 #endif
1887
1888 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1889 {
1890         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1891         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1892         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1893         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1894 }
1895
1896 void R_GLSL_Restart_f(void)
1897 {
1898         unsigned int i, limit;
1899         if (glslshaderstring)
1900                 Mem_Free(glslshaderstring);
1901         glslshaderstring = NULL;
1902         if (hlslshaderstring)
1903                 Mem_Free(hlslshaderstring);
1904         hlslshaderstring = NULL;
1905         switch(vid.renderpath)
1906         {
1907         case RENDERPATH_D3D9:
1908 #ifdef SUPPORTD3D
1909                 {
1910                         r_hlsl_permutation_t *p;
1911                         r_hlsl_permutation = NULL;
1912                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1913                         for (i = 0;i < limit;i++)
1914                         {
1915                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1916                                 {
1917                                         if (p->vertexshader)
1918                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1919                                         if (p->pixelshader)
1920                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1921                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1922                                 }
1923                         }
1924                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1925                 }
1926 #endif
1927                 break;
1928         case RENDERPATH_D3D10:
1929                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1930                 break;
1931         case RENDERPATH_D3D11:
1932                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1933                 break;
1934         case RENDERPATH_GL20:
1935         case RENDERPATH_GLES2:
1936                 {
1937                         r_glsl_permutation_t *p;
1938                         r_glsl_permutation = NULL;
1939                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1940                         for (i = 0;i < limit;i++)
1941                         {
1942                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1943                                 {
1944                                         GL_Backend_FreeProgram(p->program);
1945                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1946                                 }
1947                         }
1948                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1949                 }
1950                 break;
1951         case RENDERPATH_GL11:
1952         case RENDERPATH_GL13:
1953         case RENDERPATH_GLES1:
1954                 break;
1955         case RENDERPATH_SOFT:
1956                 break;
1957         }
1958 }
1959
1960 static void R_GLSL_DumpShader_f(void)
1961 {
1962         int i, language, mode, dupe;
1963         char *text;
1964         shadermodeinfo_t *modeinfo;
1965         qfile_t *file;
1966
1967         for (language = 0;language < 2;language++)
1968         {
1969                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1970                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1971                 {
1972                         // don't dump the same file multiple times (most or all shaders come from the same file)
1973                         for (dupe = mode - 1;dupe >= 0;dupe--)
1974                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1975                                         break;
1976                         if (dupe >= 0)
1977                                 continue;
1978                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1979                         if (!text)
1980                                 continue;
1981                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1982                         if (file)
1983                         {
1984                                 FS_Print(file, "/* The engine may define the following macros:\n");
1985                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1986                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1987                                         FS_Print(file, modeinfo[i].pretext);
1988                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1989                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1990                                 FS_Print(file, "*/\n");
1991                                 FS_Print(file, text);
1992                                 FS_Close(file);
1993                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1994                         }
1995                         else
1996                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1997                         Mem_Free(text);
1998                 }
1999         }
2000 }
2001
2002 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2003 {
2004         unsigned int permutation = 0;
2005         if (r_trippy.integer && !notrippy)
2006                 permutation |= SHADERPERMUTATION_TRIPPY;
2007         permutation |= SHADERPERMUTATION_VIEWTINT;
2008         if (first)
2009                 permutation |= SHADERPERMUTATION_DIFFUSE;
2010         if (second)
2011                 permutation |= SHADERPERMUTATION_SPECULAR;
2012         if (texturemode == GL_MODULATE)
2013                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2014         else if (texturemode == GL_ADD)
2015                 permutation |= SHADERPERMUTATION_GLOW;
2016         else if (texturemode == GL_DECAL)
2017                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2018         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2019                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2020         if (suppresstexalpha)
2021                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2022         if (!second)
2023                 texturemode = GL_MODULATE;
2024         if (vid.allowalphatocoverage)
2025                 GL_AlphaToCoverage(false);
2026         switch (vid.renderpath)
2027         {
2028         case RENDERPATH_D3D9:
2029 #ifdef SUPPORTD3D
2030                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2031                 R_Mesh_TexBind(GL20TU_FIRST , first );
2032                 R_Mesh_TexBind(GL20TU_SECOND, second);
2033                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2034                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2035 #endif
2036                 break;
2037         case RENDERPATH_D3D10:
2038                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2039                 break;
2040         case RENDERPATH_D3D11:
2041                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2042                 break;
2043         case RENDERPATH_GL20:
2044         case RENDERPATH_GLES2:
2045                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2046                 if (r_glsl_permutation->tex_Texture_First >= 0)
2047                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2048                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2049                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2050                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2051                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2052                 break;
2053         case RENDERPATH_GL13:
2054         case RENDERPATH_GLES1:
2055                 R_Mesh_TexBind(0, first );
2056                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2057                 R_Mesh_TexMatrix(0, NULL);
2058                 R_Mesh_TexBind(1, second);
2059                 if (second)
2060                 {
2061                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2062                         R_Mesh_TexMatrix(1, NULL);
2063                 }
2064                 break;
2065         case RENDERPATH_GL11:
2066                 R_Mesh_TexBind(0, first );
2067                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2068                 R_Mesh_TexMatrix(0, NULL);
2069                 break;
2070         case RENDERPATH_SOFT:
2071                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2072                 R_Mesh_TexBind(GL20TU_FIRST , first );
2073                 R_Mesh_TexBind(GL20TU_SECOND, second);
2074                 break;
2075         }
2076 }
2077
2078 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2079 {
2080         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2081 }
2082
2083 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2084 {
2085         unsigned int permutation = 0;
2086         if (r_trippy.integer && !notrippy)
2087                 permutation |= SHADERPERMUTATION_TRIPPY;
2088         if (depthrgb)
2089                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2090         if (skeletal)
2091                 permutation |= SHADERPERMUTATION_SKELETAL;
2092
2093         if (vid.allowalphatocoverage)
2094                 GL_AlphaToCoverage(false);
2095         switch (vid.renderpath)
2096         {
2097         case RENDERPATH_D3D9:
2098 #ifdef SUPPORTD3D
2099                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2100 #endif
2101                 break;
2102         case RENDERPATH_D3D10:
2103                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2104                 break;
2105         case RENDERPATH_D3D11:
2106                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2107                 break;
2108         case RENDERPATH_GL20:
2109         case RENDERPATH_GLES2:
2110                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2111 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2112                 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);
2113 #endif
2114                 break;
2115         case RENDERPATH_GL13:
2116         case RENDERPATH_GLES1:
2117                 R_Mesh_TexBind(0, 0);
2118                 R_Mesh_TexBind(1, 0);
2119                 break;
2120         case RENDERPATH_GL11:
2121                 R_Mesh_TexBind(0, 0);
2122                 break;
2123         case RENDERPATH_SOFT:
2124                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2125                 break;
2126         }
2127 }
2128
2129 extern qboolean r_shadow_usingdeferredprepass;
2130 extern rtexture_t *r_shadow_attenuationgradienttexture;
2131 extern rtexture_t *r_shadow_attenuation2dtexture;
2132 extern rtexture_t *r_shadow_attenuation3dtexture;
2133 extern qboolean r_shadow_usingshadowmap2d;
2134 extern qboolean r_shadow_usingshadowmaportho;
2135 extern float r_shadow_shadowmap_texturescale[2];
2136 extern float r_shadow_shadowmap_parameters[4];
2137 extern qboolean r_shadow_shadowmapvsdct;
2138 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2139 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2140 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2141 extern matrix4x4_t r_shadow_shadowmapmatrix;
2142 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2143 extern int r_shadow_prepass_width;
2144 extern int r_shadow_prepass_height;
2145 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2146 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2147 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2148 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2149
2150 #define BLENDFUNC_ALLOWS_COLORMOD      1
2151 #define BLENDFUNC_ALLOWS_FOG           2
2152 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2153 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2154 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2155 static int R_BlendFuncFlags(int src, int dst)
2156 {
2157         int r = 0;
2158
2159         // a blendfunc allows colormod if:
2160         // a) it can never keep the destination pixel invariant, or
2161         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2162         // this is to prevent unintended side effects from colormod
2163
2164         // a blendfunc allows fog if:
2165         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2166         // this is to prevent unintended side effects from fog
2167
2168         // these checks are the output of fogeval.pl
2169
2170         r |= BLENDFUNC_ALLOWS_COLORMOD;
2171         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2172         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2173         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2174         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2175         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2176         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2177         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2178         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2179         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2180         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2181         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2182         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2183         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2184         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2185         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2186         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2187         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2188         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2189         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2190         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2191         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192
2193         return r;
2194 }
2195
2196 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)
2197 {
2198         // select a permutation of the lighting shader appropriate to this
2199         // combination of texture, entity, light source, and fogging, only use the
2200         // minimum features necessary to avoid wasting rendering time in the
2201         // fragment shader on features that are not being used
2202         unsigned int permutation = 0;
2203         unsigned int mode = 0;
2204         int blendfuncflags;
2205         static float dummy_colormod[3] = {1, 1, 1};
2206         float *colormod = rsurface.colormod;
2207         float m16f[16];
2208         matrix4x4_t tempmatrix;
2209         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2210         if (r_trippy.integer && !notrippy)
2211                 permutation |= SHADERPERMUTATION_TRIPPY;
2212         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2213                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2214         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2215                 permutation |= SHADERPERMUTATION_OCCLUDE;
2216         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2217                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2218         if (rsurfacepass == RSURFPASS_BACKGROUND)
2219         {
2220                 // distorted background
2221                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2222                 {
2223                         mode = SHADERMODE_WATER;
2224                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2225                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2226                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2227                         {
2228                                 // this is the right thing to do for wateralpha
2229                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2230                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2231                         }
2232                         else
2233                         {
2234                                 // this is the right thing to do for entity alpha
2235                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2236                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2237                         }
2238                 }
2239                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2240                 {
2241                         mode = SHADERMODE_REFRACTION;
2242                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2243                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2244                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2245                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2246                 }
2247                 else
2248                 {
2249                         mode = SHADERMODE_GENERIC;
2250                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2251                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2252                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2253                 }
2254                 if (vid.allowalphatocoverage)
2255                         GL_AlphaToCoverage(false);
2256         }
2257         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2258         {
2259                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2260                 {
2261                         switch(rsurface.texture->offsetmapping)
2262                         {
2263                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2264                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2265                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2266                         case OFFSETMAPPING_OFF: break;
2267                         }
2268                 }
2269                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2270                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2271                 // normalmap (deferred prepass), may use alpha test on diffuse
2272                 mode = SHADERMODE_DEFERREDGEOMETRY;
2273                 GL_BlendFunc(GL_ONE, GL_ZERO);
2274                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2275                 if (vid.allowalphatocoverage)
2276                         GL_AlphaToCoverage(false);
2277         }
2278         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2279         {
2280                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2281                 {
2282                         switch(rsurface.texture->offsetmapping)
2283                         {
2284                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2285                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2287                         case OFFSETMAPPING_OFF: break;
2288                         }
2289                 }
2290                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2291                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2292                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2293                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2294                 // light source
2295                 mode = SHADERMODE_LIGHTSOURCE;
2296                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2297                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2298                 if (diffusescale > 0)
2299                         permutation |= SHADERPERMUTATION_DIFFUSE;
2300                 if (specularscale > 0)
2301                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2302                 if (r_refdef.fogenabled)
2303                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2304                 if (rsurface.texture->colormapping)
2305                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2306                 if (r_shadow_usingshadowmap2d)
2307                 {
2308                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2309                         if(r_shadow_shadowmapvsdct)
2310                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2311
2312                         if (r_shadow_shadowmap2ddepthbuffer)
2313                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2314                 }
2315                 if (rsurface.texture->reflectmasktexture)
2316                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2317                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2318                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2319                 if (vid.allowalphatocoverage)
2320                         GL_AlphaToCoverage(false);
2321         }
2322         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2323         {
2324                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2325                 {
2326                         switch(rsurface.texture->offsetmapping)
2327                         {
2328                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2329                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2330                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2331                         case OFFSETMAPPING_OFF: break;
2332                         }
2333                 }
2334                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2335                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2336                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2337                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2338                 // unshaded geometry (fullbright or ambient model lighting)
2339                 mode = SHADERMODE_FLATCOLOR;
2340                 ambientscale = diffusescale = specularscale = 0;
2341                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2342                         permutation |= SHADERPERMUTATION_GLOW;
2343                 if (r_refdef.fogenabled)
2344                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2345                 if (rsurface.texture->colormapping)
2346                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2347                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2348                 {
2349                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2350                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2351
2352                         if (r_shadow_shadowmap2ddepthbuffer)
2353                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2354                 }
2355                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2356                         permutation |= SHADERPERMUTATION_REFLECTION;
2357                 if (rsurface.texture->reflectmasktexture)
2358                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2359                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2360                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2361                 // when using alphatocoverage, we don't need alphakill
2362                 if (vid.allowalphatocoverage)
2363                 {
2364                         if (r_transparent_alphatocoverage.integer)
2365                         {
2366                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2367                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2368                         }
2369                         else
2370                                 GL_AlphaToCoverage(false);
2371                 }
2372         }
2373         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2374         {
2375                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2376                 {
2377                         switch(rsurface.texture->offsetmapping)
2378                         {
2379                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2380                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2381                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2382                         case OFFSETMAPPING_OFF: break;
2383                         }
2384                 }
2385                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2386                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2387                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2388                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2389                 // directional model lighting
2390                 mode = SHADERMODE_LIGHTDIRECTION;
2391                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2392                         permutation |= SHADERPERMUTATION_GLOW;
2393                 permutation |= SHADERPERMUTATION_DIFFUSE;
2394                 if (specularscale > 0)
2395                         permutation |= SHADERPERMUTATION_SPECULAR;
2396                 if (r_refdef.fogenabled)
2397                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2398                 if (rsurface.texture->colormapping)
2399                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2400                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2401                 {
2402                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2403                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2404
2405                         if (r_shadow_shadowmap2ddepthbuffer)
2406                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2407                 }
2408                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2409                         permutation |= SHADERPERMUTATION_REFLECTION;
2410                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2411                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2412                 if (rsurface.texture->reflectmasktexture)
2413                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2414                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2415                 {
2416                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2417                         if (r_shadow_bouncegriddirectional)
2418                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2419                 }
2420                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2422                 // when using alphatocoverage, we don't need alphakill
2423                 if (vid.allowalphatocoverage)
2424                 {
2425                         if (r_transparent_alphatocoverage.integer)
2426                         {
2427                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2428                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2429                         }
2430                         else
2431                                 GL_AlphaToCoverage(false);
2432                 }
2433         }
2434         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2435         {
2436                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2437                 {
2438                         switch(rsurface.texture->offsetmapping)
2439                         {
2440                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2441                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2442                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2443                         case OFFSETMAPPING_OFF: break;
2444                         }
2445                 }
2446                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2447                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2449                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2450                 // ambient model lighting
2451                 mode = SHADERMODE_LIGHTDIRECTION;
2452                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2453                         permutation |= SHADERPERMUTATION_GLOW;
2454                 if (r_refdef.fogenabled)
2455                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2456                 if (rsurface.texture->colormapping)
2457                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2458                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2459                 {
2460                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2461                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2462
2463                         if (r_shadow_shadowmap2ddepthbuffer)
2464                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2465                 }
2466                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2467                         permutation |= SHADERPERMUTATION_REFLECTION;
2468                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2469                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2470                 if (rsurface.texture->reflectmasktexture)
2471                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2472                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2473                 {
2474                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2475                         if (r_shadow_bouncegriddirectional)
2476                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2477                 }
2478                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2479                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2480                 // when using alphatocoverage, we don't need alphakill
2481                 if (vid.allowalphatocoverage)
2482                 {
2483                         if (r_transparent_alphatocoverage.integer)
2484                         {
2485                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2486                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2487                         }
2488                         else
2489                                 GL_AlphaToCoverage(false);
2490                 }
2491         }
2492         else
2493         {
2494                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2495                 {
2496                         switch(rsurface.texture->offsetmapping)
2497                         {
2498                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2499                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2500                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2501                         case OFFSETMAPPING_OFF: break;
2502                         }
2503                 }
2504                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2505                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2506                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2507                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2508                 // lightmapped wall
2509                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2510                         permutation |= SHADERPERMUTATION_GLOW;
2511                 if (r_refdef.fogenabled)
2512                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2513                 if (rsurface.texture->colormapping)
2514                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2515                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2516                 {
2517                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2518                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2519
2520                         if (r_shadow_shadowmap2ddepthbuffer)
2521                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2522                 }
2523                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2524                         permutation |= SHADERPERMUTATION_REFLECTION;
2525                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2526                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2527                 if (rsurface.texture->reflectmasktexture)
2528                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2529                 if (FAKELIGHT_ENABLED)
2530                 {
2531                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2532                         mode = SHADERMODE_FAKELIGHT;
2533                         permutation |= SHADERPERMUTATION_DIFFUSE;
2534                         if (specularscale > 0)
2535                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2536                 }
2537                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2538                 {
2539                         // deluxemapping (light direction texture)
2540                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2541                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2542                         else
2543                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2544                         permutation |= SHADERPERMUTATION_DIFFUSE;
2545                         if (specularscale > 0)
2546                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2547                 }
2548                 else if (r_glsl_deluxemapping.integer >= 2)
2549                 {
2550                         // fake deluxemapping (uniform light direction in tangentspace)
2551                         if (rsurface.uselightmaptexture)
2552                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2553                         else
2554                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2555                         permutation |= SHADERPERMUTATION_DIFFUSE;
2556                         if (specularscale > 0)
2557                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2558                 }
2559                 else if (rsurface.uselightmaptexture)
2560                 {
2561                         // ordinary lightmapping (q1bsp, q3bsp)
2562                         mode = SHADERMODE_LIGHTMAP;
2563                 }
2564                 else
2565                 {
2566                         // ordinary vertex coloring (q3bsp)
2567                         mode = SHADERMODE_VERTEXCOLOR;
2568                 }
2569                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2570                 {
2571                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2572                         if (r_shadow_bouncegriddirectional)
2573                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2574                 }
2575                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2576                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2577                 // when using alphatocoverage, we don't need alphakill
2578                 if (vid.allowalphatocoverage)
2579                 {
2580                         if (r_transparent_alphatocoverage.integer)
2581                         {
2582                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2583                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2584                         }
2585                         else
2586                                 GL_AlphaToCoverage(false);
2587                 }
2588         }
2589         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2590                 colormod = dummy_colormod;
2591         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2592                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2593         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2594                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2595         switch(vid.renderpath)
2596         {
2597         case RENDERPATH_D3D9:
2598 #ifdef SUPPORTD3D
2599                 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);
2600                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2601                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2602                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2603                 if (mode == SHADERMODE_LIGHTSOURCE)
2604                 {
2605                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2606                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2607                 }
2608                 else
2609                 {
2610                         if (mode == SHADERMODE_LIGHTDIRECTION)
2611                         {
2612                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2613                         }
2614                 }
2615                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2616                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2617                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2618                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2619                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2620
2621                 if (mode == SHADERMODE_LIGHTSOURCE)
2622                 {
2623                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2624                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2625                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2626                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2627                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2628
2629                         // additive passes are only darkened by fog, not tinted
2630                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2631                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2632                 }
2633                 else
2634                 {
2635                         if (mode == SHADERMODE_FLATCOLOR)
2636                         {
2637                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2638                         }
2639                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2640                         {
2641                                 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]);
2642                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2643                                 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);
2644                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2645                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2646                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2647                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2648                         }
2649                         else
2650                         {
2651                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2652                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2653                                 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);
2654                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2655                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2656                         }
2657                         // additive passes are only darkened by fog, not tinted
2658                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2659                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2660                         else
2661                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2662                         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);
2663                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2664                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2665                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2666                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2667                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2668                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2669                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2670                         if (mode == SHADERMODE_WATER)
2671                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2672                 }
2673                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2674                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2675                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2676                 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));
2677                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2678                 if (rsurface.texture->pantstexture)
2679                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2680                 else
2681                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2682                 if (rsurface.texture->shirttexture)
2683                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2684                 else
2685                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2686                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2687                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2688                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2689                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2690                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2691                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2692                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2693                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2694                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2695                         );
2696                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2697                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2698                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2699                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2700
2701                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2702                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2703                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2704                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2705                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2706                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2707                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2708                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2709                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2710                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2711                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2712                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2713                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2714                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2715                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2716                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2717                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2718                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2719                 {
2720                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2721                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2722                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2723                 }
2724                 else
2725                 {
2726                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2727                 }
2728 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2729                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2730                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2731                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2732                 {
2733                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2734                         if (rsurface.rtlight)
2735                         {
2736                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2737                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2738                         }
2739                 }
2740 #endif
2741                 break;
2742         case RENDERPATH_D3D10:
2743                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2744                 break;
2745         case RENDERPATH_D3D11:
2746                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2747                 break;
2748         case RENDERPATH_GL20:
2749         case RENDERPATH_GLES2:
2750                 if (!vid.useinterleavedarrays)
2751                 {
2752                         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);
2753                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2754                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2755                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2756                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2757                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2758                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2759                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2760                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2761                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2762                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2763                 }
2764                 else
2765                 {
2766                         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);
2767                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2768                 }
2769                 // this has to be after RSurf_PrepareVerticesForBatch
2770                 if (rsurface.batchskeletaltransform3x4buffer)
2771                         permutation |= SHADERPERMUTATION_SKELETAL;
2772                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2773 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2774                 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);
2775 #endif
2776                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2777                 if (mode == SHADERMODE_LIGHTSOURCE)
2778                 {
2779                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2780                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2781                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2782                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2783                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2784                         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);
2785         
2786                         // additive passes are only darkened by fog, not tinted
2787                         if (r_glsl_permutation->loc_FogColor >= 0)
2788                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2789                         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);
2790                 }
2791                 else
2792                 {
2793                         if (mode == SHADERMODE_FLATCOLOR)
2794                         {
2795                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2796                         }
2797                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2798                         {
2799                                 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]);
2800                                 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]);
2801                                 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);
2802                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2803                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2804                                 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]);
2805                                 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]);
2806                         }
2807                         else
2808                         {
2809                                 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]);
2810                                 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]);
2811                                 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);
2812                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2813                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2814                         }
2815                         // additive passes are only darkened by fog, not tinted
2816                         if (r_glsl_permutation->loc_FogColor >= 0)
2817                         {
2818                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2819                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2820                                 else
2821                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2822                         }
2823                         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);
2824                         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]);
2825                         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]);
2826                         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]);
2827                         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]);
2828                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2829                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2830                         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);
2831                         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]);
2832                 }
2833                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2834                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2835                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2836                 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]);
2837                 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]);
2838
2839                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2840                 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));
2841                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2842                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2843                 {
2844                         if (rsurface.texture->pantstexture)
2845                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2846                         else
2847                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2848                 }
2849                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2850                 {
2851                         if (rsurface.texture->shirttexture)
2852                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2853                         else
2854                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2855                 }
2856                 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]);
2857                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2858                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2859                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2860                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2861                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2862                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2863                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2864                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2865                         );
2866                 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);
2867                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2868                 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]);
2869                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2870                 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);}
2871                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2872
2873                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2874                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2875                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2876                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2877                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2878                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2879                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2880                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2881                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2882                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2883                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2884                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2885                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2886                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2887                 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);
2888                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2889                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2890                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2891                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2892                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2893                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2894                 {
2895                         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);
2896                         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);
2897                         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);
2898                 }
2899                 else
2900                 {
2901                         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);
2902                 }
2903                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2904                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2905                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2906                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2907                 {
2908                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2909                         if (rsurface.rtlight)
2910                         {
2911                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2912                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2913                         }
2914                 }
2915                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2916                 CHECKGLERROR
2917                 break;
2918         case RENDERPATH_GL11:
2919         case RENDERPATH_GL13:
2920         case RENDERPATH_GLES1:
2921                 break;
2922         case RENDERPATH_SOFT:
2923                 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);
2924                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2925                 R_SetupShader_SetPermutationSoft(mode, permutation);
2926                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2927                 if (mode == SHADERMODE_LIGHTSOURCE)
2928                 {
2929                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2930                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2931                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2932                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2933                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2934                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2935         
2936                         // additive passes are only darkened by fog, not tinted
2937                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2938                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2939                 }
2940                 else
2941                 {
2942                         if (mode == SHADERMODE_FLATCOLOR)
2943                         {
2944                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2945                         }
2946                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2947                         {
2948                                 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]);
2949                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2950                                 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);
2951                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2952                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2953                                 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]);
2954                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2955                         }
2956                         else
2957                         {
2958                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2959                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2960                                 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);
2961                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2962                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2963                         }
2964                         // additive passes are only darkened by fog, not tinted
2965                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2966                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2967                         else
2968                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2969                         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);
2970                         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]);
2971                         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]);
2972                         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]);
2973                         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]);
2974                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2975                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2976                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2977                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2978                 }
2979                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2980                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2981                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2982                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2983                 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]);
2984
2985                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2986                 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));
2987                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2988                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2989                 {
2990                         if (rsurface.texture->pantstexture)
2991                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2992                         else
2993                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2994                 }
2995                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2996                 {
2997                         if (rsurface.texture->shirttexture)
2998                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2999                         else
3000                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3001                 }
3002                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3003                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3004                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3005                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3006                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3007                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3008                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3009                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3010                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3011                         );
3012                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3013                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3014                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3015                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3016
3017                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3018                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3019                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3020                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3021                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3022                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3023                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3024                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3025                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3026                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3027                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3028                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3029                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3030                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3031                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3032                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3033                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3034                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3035                 {
3036                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3037                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3038                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3039                 }
3040                 else
3041                 {
3042                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3043                 }
3044 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3045                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3046                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3047                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3048                 {
3049                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3050                         if (rsurface.rtlight)
3051                         {
3052                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3053                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3054                         }
3055                 }
3056                 break;
3057         }
3058 }
3059
3060 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3061 {
3062         // select a permutation of the lighting shader appropriate to this
3063         // combination of texture, entity, light source, and fogging, only use the
3064         // minimum features necessary to avoid wasting rendering time in the
3065         // fragment shader on features that are not being used
3066         unsigned int permutation = 0;
3067         unsigned int mode = 0;
3068         const float *lightcolorbase = rtlight->currentcolor;
3069         float ambientscale = rtlight->ambientscale;
3070         float diffusescale = rtlight->diffusescale;
3071         float specularscale = rtlight->specularscale;
3072         // this is the location of the light in view space
3073         vec3_t viewlightorigin;
3074         // this transforms from view space (camera) to light space (cubemap)
3075         matrix4x4_t viewtolight;
3076         matrix4x4_t lighttoview;
3077         float viewtolight16f[16];
3078         // light source
3079         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3080         if (rtlight->currentcubemap != r_texture_whitecube)
3081                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3082         if (diffusescale > 0)
3083                 permutation |= SHADERPERMUTATION_DIFFUSE;
3084         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3085                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3086         if (r_shadow_usingshadowmap2d)
3087         {
3088                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3089                 if (r_shadow_shadowmapvsdct)
3090                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3091
3092                 if (r_shadow_shadowmap2ddepthbuffer)
3093                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3094         }
3095         if (vid.allowalphatocoverage)
3096                 GL_AlphaToCoverage(false);
3097         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3098         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3099         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3100         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3101         switch(vid.renderpath)
3102         {
3103         case RENDERPATH_D3D9:
3104 #ifdef SUPPORTD3D
3105                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3106                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3107                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3108                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3109                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3110                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3111                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3112                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3113                 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);
3114                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3115                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3116
3117                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3118                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3119                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3120                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3121                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3122 #endif
3123                 break;
3124         case RENDERPATH_D3D10:
3125                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3126                 break;
3127         case RENDERPATH_D3D11:
3128                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3129                 break;
3130         case RENDERPATH_GL20:
3131         case RENDERPATH_GLES2:
3132                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3133                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3134                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3135                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3136                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3137                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3138                 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]);
3139                 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]);
3140                 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);
3141                 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]);
3142                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3143
3144                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3145                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3146                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3147                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3148                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3149                 break;
3150         case RENDERPATH_GL11:
3151         case RENDERPATH_GL13:
3152         case RENDERPATH_GLES1:
3153                 break;
3154         case RENDERPATH_SOFT:
3155                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3156                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3157                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3158                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3159                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3160                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3161                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3162                 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]);
3163                 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);
3164                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3165                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3166
3167                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3168                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3169                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3170                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3171                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3172                 break;
3173         }
3174 }
3175
3176 #define SKINFRAME_HASH 1024
3177
3178 typedef struct
3179 {
3180         unsigned int loadsequence; // incremented each level change
3181         memexpandablearray_t array;
3182         skinframe_t *hash[SKINFRAME_HASH];
3183 }
3184 r_skinframe_t;
3185 r_skinframe_t r_skinframe;
3186
3187 void R_SkinFrame_PrepareForPurge(void)
3188 {
3189         r_skinframe.loadsequence++;
3190         // wrap it without hitting zero
3191         if (r_skinframe.loadsequence >= 200)
3192                 r_skinframe.loadsequence = 1;
3193 }
3194
3195 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3196 {
3197         if (!skinframe)
3198                 return;
3199         // mark the skinframe as used for the purging code
3200         skinframe->loadsequence = r_skinframe.loadsequence;
3201 }
3202
3203 void R_SkinFrame_Purge(void)
3204 {
3205         int i;
3206         skinframe_t *s;
3207         for (i = 0;i < SKINFRAME_HASH;i++)
3208         {
3209                 for (s = r_skinframe.hash[i];s;s = s->next)
3210                 {
3211                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3212                         {
3213                                 if (s->merged == s->base)
3214                                         s->merged = NULL;
3215                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3216                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3217                                 R_PurgeTexture(s->merged);s->merged = NULL;
3218                                 R_PurgeTexture(s->base  );s->base   = NULL;
3219                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3220                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3221                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3222                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3223                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3224                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3225                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3226                                 s->loadsequence = 0;
3227                         }
3228                 }
3229         }
3230 }
3231
3232 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3233         skinframe_t *item;
3234         char basename[MAX_QPATH];
3235
3236         Image_StripImageExtension(name, basename, sizeof(basename));
3237
3238         if( last == NULL ) {
3239                 int hashindex;
3240                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3241                 item = r_skinframe.hash[hashindex];
3242         } else {
3243                 item = last->next;
3244         }
3245
3246         // linearly search through the hash bucket
3247         for( ; item ; item = item->next ) {
3248                 if( !strcmp( item->basename, basename ) ) {
3249                         return item;
3250                 }
3251         }
3252         return NULL;
3253 }
3254
3255 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3256 {
3257         skinframe_t *item;
3258         int hashindex;
3259         char basename[MAX_QPATH];
3260
3261         Image_StripImageExtension(name, basename, sizeof(basename));
3262
3263         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3264         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3265                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3266                         break;
3267
3268         if (!item) {
3269                 rtexture_t *dyntexture;
3270                 // check whether its a dynamic texture
3271                 dyntexture = CL_GetDynTexture( basename );
3272                 if (!add && !dyntexture)
3273                         return NULL;
3274                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3275                 memset(item, 0, sizeof(*item));
3276                 strlcpy(item->basename, basename, sizeof(item->basename));
3277                 item->base = dyntexture; // either NULL or dyntexture handle
3278                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3279                 item->comparewidth = comparewidth;
3280                 item->compareheight = compareheight;
3281                 item->comparecrc = comparecrc;
3282                 item->next = r_skinframe.hash[hashindex];
3283                 r_skinframe.hash[hashindex] = item;
3284         }
3285         else if (textureflags & TEXF_FORCE_RELOAD)
3286         {
3287                 rtexture_t *dyntexture;
3288                 // check whether its a dynamic texture
3289                 dyntexture = CL_GetDynTexture( basename );
3290                 if (!add && !dyntexture)
3291                         return NULL;
3292                 if (item->merged == item->base)
3293                         item->merged = NULL;
3294                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3295                 R_PurgeTexture(item->stain );item->stain  = NULL;
3296                 R_PurgeTexture(item->merged);item->merged = NULL;
3297                 R_PurgeTexture(item->base  );item->base   = NULL;
3298                 R_PurgeTexture(item->pants );item->pants  = NULL;
3299                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3300                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3301                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3302                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3303                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3304         R_PurgeTexture(item->reflect);item->reflect = NULL;
3305                 item->loadsequence = 0;
3306         }
3307         else if( item->base == NULL )
3308         {
3309                 rtexture_t *dyntexture;
3310                 // check whether its a dynamic texture
3311                 // 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]
3312                 dyntexture = CL_GetDynTexture( basename );
3313                 item->base = dyntexture; // either NULL or dyntexture handle
3314         }
3315
3316         R_SkinFrame_MarkUsed(item);
3317         return item;
3318 }
3319
3320 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3321         { \
3322                 unsigned long long avgcolor[5], wsum; \
3323                 int pix, comp, w; \
3324                 avgcolor[0] = 0; \
3325                 avgcolor[1] = 0; \
3326                 avgcolor[2] = 0; \
3327                 avgcolor[3] = 0; \
3328                 avgcolor[4] = 0; \
3329                 wsum = 0; \
3330                 for(pix = 0; pix < cnt; ++pix) \
3331                 { \
3332                         w = 0; \
3333                         for(comp = 0; comp < 3; ++comp) \
3334                                 w += getpixel; \
3335                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3336                         { \
3337                                 ++wsum; \
3338                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3339                                 w = getpixel; \
3340                                 for(comp = 0; comp < 3; ++comp) \
3341                                         avgcolor[comp] += getpixel * w; \
3342                                 avgcolor[3] += w; \
3343                         } \
3344                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3345                         avgcolor[4] += getpixel; \
3346                 } \
3347                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3348                         avgcolor[3] = 1; \
3349                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3350                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3351                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3352                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3353         }
3354
3355 extern cvar_t gl_picmip;
3356 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3357 {
3358         int j;
3359         unsigned char *pixels;
3360         unsigned char *bumppixels;
3361         unsigned char *basepixels = NULL;
3362         int basepixels_width = 0;
3363         int basepixels_height = 0;
3364         skinframe_t *skinframe;
3365         rtexture_t *ddsbase = NULL;
3366         qboolean ddshasalpha = false;
3367         float ddsavgcolor[4];
3368         char basename[MAX_QPATH];
3369         int miplevel = R_PicmipForFlags(textureflags);
3370         int savemiplevel = miplevel;
3371         int mymiplevel;
3372         char vabuf[1024];
3373
3374         if (cls.state == ca_dedicated)
3375                 return NULL;
3376
3377         // return an existing skinframe if already loaded
3378         // if loading of the first image fails, don't make a new skinframe as it
3379         // would cause all future lookups of this to be missing
3380         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3381         if (skinframe && skinframe->base)
3382                 return skinframe;
3383
3384         Image_StripImageExtension(name, basename, sizeof(basename));
3385
3386         // check for DDS texture file first
3387         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3388         {
3389                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3390                 if (basepixels == NULL)
3391                         return NULL;
3392         }
3393
3394         // FIXME handle miplevel
3395
3396         if (developer_loading.integer)
3397                 Con_Printf("loading skin \"%s\"\n", name);
3398
3399         // we've got some pixels to store, so really allocate this new texture now
3400         if (!skinframe)
3401                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3402         textureflags &= ~TEXF_FORCE_RELOAD;
3403         skinframe->stain = NULL;
3404         skinframe->merged = NULL;
3405         skinframe->base = NULL;
3406         skinframe->pants = NULL;
3407         skinframe->shirt = NULL;
3408         skinframe->nmap = NULL;
3409         skinframe->gloss = NULL;
3410         skinframe->glow = NULL;
3411         skinframe->fog = NULL;
3412         skinframe->reflect = NULL;
3413         skinframe->hasalpha = false;
3414         // we could store the q2animname here too
3415
3416         if (ddsbase)
3417         {
3418                 skinframe->base = ddsbase;
3419                 skinframe->hasalpha = ddshasalpha;
3420                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3421                 if (r_loadfog && skinframe->hasalpha)
3422                         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);
3423                 //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]);
3424         }
3425         else
3426         {
3427                 basepixels_width = image_width;
3428                 basepixels_height = image_height;
3429                 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);
3430                 if (textureflags & TEXF_ALPHA)
3431                 {
3432                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3433                         {
3434                                 if (basepixels[j] < 255)
3435                                 {
3436                                         skinframe->hasalpha = true;
3437                                         break;
3438                                 }
3439                         }
3440                         if (r_loadfog && skinframe->hasalpha)
3441                         {
3442                                 // has transparent pixels
3443                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3444                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3445                                 {
3446                                         pixels[j+0] = 255;
3447                                         pixels[j+1] = 255;
3448                                         pixels[j+2] = 255;
3449                                         pixels[j+3] = basepixels[j+3];
3450                                 }
3451                                 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);
3452                                 Mem_Free(pixels);
3453                         }
3454                 }
3455                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3456 #ifndef USE_GLES2
3457                 //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]);
3458                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3459                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3460                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3461                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3462 #endif
3463         }
3464
3465         if (r_loaddds)
3466         {
3467                 mymiplevel = savemiplevel;
3468                 if (r_loadnormalmap)
3469                         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);
3470                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3471                 if (r_loadgloss)
3472                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3473                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3474                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3475                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3476         }
3477
3478         // _norm is the name used by tenebrae and has been adopted as standard
3479         if (r_loadnormalmap && skinframe->nmap == NULL)
3480         {
3481                 mymiplevel = savemiplevel;
3482                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3483                 {
3484                         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);
3485                         Mem_Free(pixels);
3486                         pixels = NULL;
3487                 }
3488                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3489                 {
3490                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3491                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3492                         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);
3493                         Mem_Free(pixels);
3494                         Mem_Free(bumppixels);
3495                 }
3496                 else if (r_shadow_bumpscale_basetexture.value > 0)
3497                 {
3498                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3499                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3500                         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);
3501                         Mem_Free(pixels);
3502                 }
3503 #ifndef USE_GLES2
3504                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3505                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3506 #endif
3507         }
3508
3509         // _luma is supported only for tenebrae compatibility
3510         // _glow is the preferred name
3511         mymiplevel = savemiplevel;
3512         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))))
3513         {
3514                 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);
3515 #ifndef USE_GLES2
3516                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3517                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3518 #endif
3519                 Mem_Free(pixels);pixels = NULL;
3520         }
3521
3522         mymiplevel = savemiplevel;
3523         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3524         {
3525                 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);
3526 #ifndef USE_GLES2
3527                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3528                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3529 #endif
3530                 Mem_Free(pixels);
3531                 pixels = NULL;
3532         }
3533
3534         mymiplevel = savemiplevel;
3535         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3536         {
3537                 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);
3538 #ifndef USE_GLES2
3539                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3540                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3541 #endif
3542                 Mem_Free(pixels);
3543                 pixels = NULL;
3544         }
3545
3546         mymiplevel = savemiplevel;
3547         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3548         {
3549                 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);
3550 #ifndef USE_GLES2
3551                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3552                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3553 #endif
3554                 Mem_Free(pixels);
3555                 pixels = NULL;
3556         }
3557
3558         mymiplevel = savemiplevel;
3559         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3560         {
3561                 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);
3562 #ifndef USE_GLES2
3563                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3564                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3565 #endif
3566                 Mem_Free(pixels);
3567                 pixels = NULL;
3568         }
3569
3570         if (basepixels)
3571                 Mem_Free(basepixels);
3572
3573         return skinframe;
3574 }
3575
3576 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3577 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3578 {
3579         int i;
3580         unsigned char *temp1, *temp2;
3581         skinframe_t *skinframe;
3582         char vabuf[1024];
3583
3584         if (cls.state == ca_dedicated)
3585                 return NULL;
3586
3587         // if already loaded just return it, otherwise make a new skinframe
3588         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3589         if (skinframe->base)
3590                 return skinframe;
3591         textureflags &= ~TEXF_FORCE_RELOAD;
3592
3593         skinframe->stain = NULL;
3594         skinframe->merged = NULL;
3595         skinframe->base = NULL;
3596         skinframe->pants = NULL;
3597         skinframe->shirt = NULL;
3598         skinframe->nmap = NULL;
3599         skinframe->gloss = NULL;
3600         skinframe->glow = NULL;
3601         skinframe->fog = NULL;
3602         skinframe->reflect = NULL;
3603         skinframe->hasalpha = false;
3604
3605         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3606         if (!skindata)
3607                 return NULL;
3608
3609         if (developer_loading.integer)
3610                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3611
3612         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3613         {
3614                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3615                 temp2 = temp1 + width * height * 4;
3616                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3617                 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);
3618                 Mem_Free(temp1);
3619         }
3620         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3621         if (textureflags & TEXF_ALPHA)
3622         {
3623                 for (i = 3;i < width * height * 4;i += 4)
3624                 {
3625                         if (skindata[i] < 255)
3626                         {
3627                                 skinframe->hasalpha = true;
3628                                 break;
3629                         }
3630                 }
3631                 if (r_loadfog && skinframe->hasalpha)
3632                 {
3633                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3634                         memcpy(fogpixels, skindata, width * height * 4);
3635                         for (i = 0;i < width * height * 4;i += 4)
3636                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3637                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3638                         Mem_Free(fogpixels);
3639                 }
3640         }
3641
3642         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3643         //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]);
3644
3645         return skinframe;
3646 }
3647
3648 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3649 {
3650         int i;
3651         int featuresmask;
3652         skinframe_t *skinframe;
3653
3654         if (cls.state == ca_dedicated)
3655                 return NULL;
3656
3657         // if already loaded just return it, otherwise make a new skinframe
3658         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3659         if (skinframe->base)
3660                 return skinframe;
3661         //textureflags &= ~TEXF_FORCE_RELOAD;
3662
3663         skinframe->stain = NULL;
3664         skinframe->merged = NULL;
3665         skinframe->base = NULL;
3666         skinframe->pants = NULL;
3667         skinframe->shirt = NULL;
3668         skinframe->nmap = NULL;
3669         skinframe->gloss = NULL;
3670         skinframe->glow = NULL;
3671         skinframe->fog = NULL;
3672         skinframe->reflect = NULL;
3673         skinframe->hasalpha = false;
3674
3675         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3676         if (!skindata)
3677                 return NULL;
3678
3679         if (developer_loading.integer)
3680                 Con_Printf("loading quake skin \"%s\"\n", name);
3681
3682         // 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)
3683         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3684         memcpy(skinframe->qpixels, skindata, width*height);
3685         skinframe->qwidth = width;
3686         skinframe->qheight = height;
3687
3688         featuresmask = 0;
3689         for (i = 0;i < width * height;i++)
3690                 featuresmask |= palette_featureflags[skindata[i]];
3691
3692         skinframe->hasalpha = false;
3693         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3694         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3695         skinframe->qgeneratemerged = true;
3696         skinframe->qgeneratebase = skinframe->qhascolormapping;
3697         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3698
3699         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3700         //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]);
3701
3702         return skinframe;
3703 }
3704
3705 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3706 {
3707         int width;
3708         int height;
3709         unsigned char *skindata;
3710         char vabuf[1024];
3711
3712         if (!skinframe->qpixels)
3713                 return;
3714
3715         if (!skinframe->qhascolormapping)
3716                 colormapped = false;
3717
3718         if (colormapped)
3719         {
3720                 if (!skinframe->qgeneratebase)
3721                         return;
3722         }
3723         else
3724         {
3725                 if (!skinframe->qgeneratemerged)
3726                         return;
3727         }
3728
3729         width = skinframe->qwidth;
3730         height = skinframe->qheight;
3731         skindata = skinframe->qpixels;
3732
3733         if (skinframe->qgeneratenmap)
3734         {
3735                 unsigned char *temp1, *temp2;
3736                 skinframe->qgeneratenmap = false;
3737                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3738                 temp2 = temp1 + width * height * 4;
3739                 // use either a custom palette or the quake palette
3740                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3741                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3742                 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);
3743                 Mem_Free(temp1);
3744         }
3745
3746         if (skinframe->qgenerateglow)
3747         {
3748                 skinframe->qgenerateglow = false;
3749                 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
3750         }
3751
3752         if (colormapped)
3753         {
3754                 skinframe->qgeneratebase = false;
3755                 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);
3756                 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);
3757                 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);
3758         }
3759         else
3760         {
3761                 skinframe->qgeneratemerged = false;
3762                 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);
3763         }
3764
3765         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3766         {
3767                 Mem_Free(skinframe->qpixels);
3768                 skinframe->qpixels = NULL;
3769         }
3770 }
3771
3772 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)
3773 {
3774         int i;
3775         skinframe_t *skinframe;
3776         char vabuf[1024];
3777
3778         if (cls.state == ca_dedicated)
3779                 return NULL;
3780
3781         // if already loaded just return it, otherwise make a new skinframe
3782         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3783         if (skinframe->base)
3784                 return skinframe;
3785         textureflags &= ~TEXF_FORCE_RELOAD;
3786
3787         skinframe->stain = NULL;
3788         skinframe->merged = NULL;
3789         skinframe->base = NULL;
3790         skinframe->pants = NULL;
3791         skinframe->shirt = NULL;
3792         skinframe->nmap = NULL;
3793         skinframe->gloss = NULL;
3794         skinframe->glow = NULL;
3795         skinframe->fog = NULL;
3796         skinframe->reflect = NULL;
3797         skinframe->hasalpha = false;
3798
3799         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3800         if (!skindata)
3801                 return NULL;
3802
3803         if (developer_loading.integer)
3804                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3805
3806         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3807         if (textureflags & TEXF_ALPHA)
3808         {
3809                 for (i = 0;i < width * height;i++)
3810                 {
3811                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3812                         {
3813                                 skinframe->hasalpha = true;
3814                                 break;
3815                         }
3816                 }
3817                 if (r_loadfog && skinframe->hasalpha)
3818                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3819         }
3820
3821         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3822         //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]);
3823
3824         return skinframe;
3825 }
3826
3827 skinframe_t *R_SkinFrame_LoadMissing(void)
3828 {
3829         skinframe_t *skinframe;
3830
3831         if (cls.state == ca_dedicated)
3832                 return NULL;
3833
3834         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3835         skinframe->stain = NULL;
3836         skinframe->merged = NULL;
3837         skinframe->base = NULL;
3838         skinframe->pants = NULL;
3839         skinframe->shirt = NULL;
3840         skinframe->nmap = NULL;
3841         skinframe->gloss = NULL;
3842         skinframe->glow = NULL;
3843         skinframe->fog = NULL;
3844         skinframe->reflect = NULL;
3845         skinframe->hasalpha = false;
3846
3847         skinframe->avgcolor[0] = rand() / RAND_MAX;
3848         skinframe->avgcolor[1] = rand() / RAND_MAX;
3849         skinframe->avgcolor[2] = rand() / RAND_MAX;
3850         skinframe->avgcolor[3] = 1;
3851
3852         return skinframe;
3853 }
3854
3855 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3856 typedef struct suffixinfo_s
3857 {
3858         const char *suffix;
3859         qboolean flipx, flipy, flipdiagonal;
3860 }
3861 suffixinfo_t;
3862 static suffixinfo_t suffix[3][6] =
3863 {
3864         {
3865                 {"px",   false, false, false},
3866                 {"nx",   false, false, false},
3867                 {"py",   false, false, false},
3868                 {"ny",   false, false, false},
3869                 {"pz",   false, false, false},
3870                 {"nz",   false, false, false}
3871         },
3872         {
3873                 {"posx", false, false, false},
3874                 {"negx", false, false, false},
3875                 {"posy", false, false, false},
3876                 {"negy", false, false, false},
3877                 {"posz", false, false, false},
3878                 {"negz", false, false, false}
3879         },
3880         {
3881                 {"rt",    true, false,  true},
3882                 {"lf",   false,  true,  true},
3883                 {"ft",    true,  true, false},
3884                 {"bk",   false, false, false},
3885                 {"up",    true, false,  true},
3886                 {"dn",    true, false,  true}
3887         }
3888 };
3889
3890 static int componentorder[4] = {0, 1, 2, 3};
3891
3892 static rtexture_t *R_LoadCubemap(const char *basename)
3893 {
3894         int i, j, cubemapsize;
3895         unsigned char *cubemappixels, *image_buffer;
3896         rtexture_t *cubemaptexture;
3897         char name[256];
3898         // must start 0 so the first loadimagepixels has no requested width/height
3899         cubemapsize = 0;
3900         cubemappixels = NULL;
3901         cubemaptexture = NULL;
3902         // keep trying different suffix groups (posx, px, rt) until one loads
3903         for (j = 0;j < 3 && !cubemappixels;j++)
3904         {
3905                 // load the 6 images in the suffix group
3906                 for (i = 0;i < 6;i++)
3907                 {
3908                         // generate an image name based on the base and and suffix
3909                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3910                         // load it
3911                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3912                         {
3913                                 // an image loaded, make sure width and height are equal
3914                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3915                                 {
3916                                         // if this is the first image to load successfully, allocate the cubemap memory
3917                                         if (!cubemappixels && image_width >= 1)
3918                                         {
3919                                                 cubemapsize = image_width;
3920                                                 // note this clears to black, so unavailable sides are black
3921                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3922                                         }
3923                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3924                                         if (cubemappixels)
3925                                                 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);
3926                                 }
3927                                 else
3928                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3929                                 // free the image
3930                                 Mem_Free(image_buffer);
3931                         }
3932                 }
3933         }
3934         // if a cubemap loaded, upload it
3935         if (cubemappixels)
3936         {
3937                 if (developer_loading.integer)
3938                         Con_Printf("loading cubemap \"%s\"\n", basename);
3939
3940                 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);
3941                 Mem_Free(cubemappixels);
3942         }
3943         else
3944         {
3945                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3946                 if (developer_loading.integer)
3947                 {
3948                         Con_Printf("(tried tried images ");
3949                         for (j = 0;j < 3;j++)
3950                                 for (i = 0;i < 6;i++)
3951                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3952                         Con_Print(" and was unable to find any of them).\n");
3953                 }
3954         }
3955         return cubemaptexture;
3956 }
3957
3958 rtexture_t *R_GetCubemap(const char *basename)
3959 {
3960         int i;
3961         for (i = 0;i < r_texture_numcubemaps;i++)
3962                 if (r_texture_cubemaps[i] != NULL)
3963                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3964                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3965         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3966                 return r_texture_whitecube;
3967         r_texture_numcubemaps++;
3968         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3969         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3970         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3971         return r_texture_cubemaps[i]->texture;
3972 }
3973
3974 static void R_Main_FreeViewCache(void)
3975 {
3976         if (r_refdef.viewcache.entityvisible)
3977                 Mem_Free(r_refdef.viewcache.entityvisible);
3978         if (r_refdef.viewcache.world_pvsbits)
3979                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3980         if (r_refdef.viewcache.world_leafvisible)
3981                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3982         if (r_refdef.viewcache.world_surfacevisible)
3983                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3984         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3985 }
3986
3987 static void R_Main_ResizeViewCache(void)
3988 {
3989         int numentities = r_refdef.scene.numentities;
3990         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3991         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3992         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3993         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3994         if (r_refdef.viewcache.maxentities < numentities)
3995         {
3996                 r_refdef.viewcache.maxentities = numentities;
3997                 if (r_refdef.viewcache.entityvisible)
3998                         Mem_Free(r_refdef.viewcache.entityvisible);
3999                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4000         }
4001         if (r_refdef.viewcache.world_numclusters != numclusters)
4002         {
4003                 r_refdef.viewcache.world_numclusters = numclusters;
4004                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4005                 if (r_refdef.viewcache.world_pvsbits)
4006                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4007                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4008         }
4009         if (r_refdef.viewcache.world_numleafs != numleafs)
4010         {
4011                 r_refdef.viewcache.world_numleafs = numleafs;
4012                 if (r_refdef.viewcache.world_leafvisible)
4013                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4014                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4015         }
4016         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4017         {
4018                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4019                 if (r_refdef.viewcache.world_surfacevisible)
4020                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4021                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4022         }
4023 }
4024
4025 extern rtexture_t *loadingscreentexture;
4026 static void gl_main_start(void)
4027 {
4028         loadingscreentexture = NULL;
4029         r_texture_blanknormalmap = NULL;
4030         r_texture_white = NULL;
4031         r_texture_grey128 = NULL;
4032         r_texture_black = NULL;
4033         r_texture_whitecube = NULL;
4034         r_texture_normalizationcube = NULL;
4035         r_texture_fogattenuation = NULL;
4036         r_texture_fogheighttexture = NULL;
4037         r_texture_gammaramps = NULL;
4038         r_texture_numcubemaps = 0;
4039         r_uniformbufferalignment = 32;
4040
4041         r_loaddds = r_texture_dds_load.integer != 0;
4042         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4043
4044         switch(vid.renderpath)
4045         {
4046         case RENDERPATH_GL20:
4047         case RENDERPATH_D3D9:
4048         case RENDERPATH_D3D10:
4049         case RENDERPATH_D3D11:
4050         case RENDERPATH_SOFT:
4051         case RENDERPATH_GLES2:
4052                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4053                 Cvar_SetValueQuick(&gl_combine, 1);
4054                 Cvar_SetValueQuick(&r_glsl, 1);
4055                 r_loadnormalmap = true;
4056                 r_loadgloss = true;
4057                 r_loadfog = false;
4058 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4059                 if (vid.support.arb_uniform_buffer_object)
4060                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4061 #endif
4062                         break;
4063         case RENDERPATH_GL13:
4064         case RENDERPATH_GLES1:
4065                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4066                 Cvar_SetValueQuick(&gl_combine, 1);
4067                 Cvar_SetValueQuick(&r_glsl, 0);
4068                 r_loadnormalmap = false;
4069                 r_loadgloss = false;
4070                 r_loadfog = true;
4071                 break;
4072         case RENDERPATH_GL11:
4073                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4074                 Cvar_SetValueQuick(&gl_combine, 0);
4075                 Cvar_SetValueQuick(&r_glsl, 0);
4076                 r_loadnormalmap = false;
4077                 r_loadgloss = false;
4078                 r_loadfog = true;
4079                 break;
4080         }
4081
4082         R_AnimCache_Free();
4083         R_FrameData_Reset();
4084         R_BufferData_Reset();
4085
4086         r_numqueries = 0;
4087         r_maxqueries = 0;
4088         memset(r_queries, 0, sizeof(r_queries));
4089
4090         r_qwskincache = NULL;
4091         r_qwskincache_size = 0;
4092
4093         // due to caching of texture_t references, the collision cache must be reset
4094         Collision_Cache_Reset(true);
4095
4096         // set up r_skinframe loading system for textures
4097         memset(&r_skinframe, 0, sizeof(r_skinframe));
4098         r_skinframe.loadsequence = 1;
4099         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4100
4101         r_main_texturepool = R_AllocTexturePool();
4102         R_BuildBlankTextures();
4103         R_BuildNoTexture();
4104         if (vid.support.arb_texture_cube_map)
4105         {
4106                 R_BuildWhiteCube();
4107                 R_BuildNormalizationCube();
4108         }
4109         r_texture_fogattenuation = NULL;
4110         r_texture_fogheighttexture = NULL;
4111         r_texture_gammaramps = NULL;
4112         //r_texture_fogintensity = NULL;
4113         memset(&r_fb, 0, sizeof(r_fb));
4114         r_glsl_permutation = NULL;
4115         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4116         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4117         glslshaderstring = NULL;
4118 #ifdef SUPPORTD3D
4119         r_hlsl_permutation = NULL;
4120         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4121         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4122 #endif
4123         hlslshaderstring = NULL;
4124         memset(&r_svbsp, 0, sizeof (r_svbsp));
4125
4126         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4127         r_texture_numcubemaps = 0;
4128
4129         r_refdef.fogmasktable_density = 0;
4130
4131 #ifdef __ANDROID__
4132         // For Steelstorm Android
4133         // FIXME CACHE the program and reload
4134         // FIXME see possible combinations for SS:BR android
4135         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4136         R_SetupShader_SetPermutationGLSL(0, 12);
4137         R_SetupShader_SetPermutationGLSL(0, 13);
4138         R_SetupShader_SetPermutationGLSL(0, 8388621);
4139         R_SetupShader_SetPermutationGLSL(3, 0);
4140         R_SetupShader_SetPermutationGLSL(3, 2048);
4141         R_SetupShader_SetPermutationGLSL(5, 0);
4142         R_SetupShader_SetPermutationGLSL(5, 2);
4143         R_SetupShader_SetPermutationGLSL(5, 2048);
4144         R_SetupShader_SetPermutationGLSL(5, 8388608);
4145         R_SetupShader_SetPermutationGLSL(11, 1);
4146         R_SetupShader_SetPermutationGLSL(11, 2049);
4147         R_SetupShader_SetPermutationGLSL(11, 8193);
4148         R_SetupShader_SetPermutationGLSL(11, 10241);
4149         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4150 #endif
4151 }
4152
4153 static void gl_main_shutdown(void)
4154 {
4155         R_AnimCache_Free();
4156         R_FrameData_Reset();
4157         R_BufferData_Reset();
4158
4159         R_Main_FreeViewCache();
4160
4161         switch(vid.renderpath)
4162         {
4163         case RENDERPATH_GL11:
4164         case RENDERPATH_GL13:
4165         case RENDERPATH_GL20:
4166         case RENDERPATH_GLES1:
4167         case RENDERPATH_GLES2:
4168 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4169                 if (r_maxqueries)
4170                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4171 #endif
4172                 break;
4173         case RENDERPATH_D3D9:
4174                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4175                 break;
4176         case RENDERPATH_D3D10:
4177                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4178                 break;
4179         case RENDERPATH_D3D11:
4180                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4181                 break;
4182         case RENDERPATH_SOFT:
4183                 break;
4184         }
4185
4186         r_numqueries = 0;
4187         r_maxqueries = 0;
4188         memset(r_queries, 0, sizeof(r_queries));
4189
4190         r_qwskincache = NULL;
4191         r_qwskincache_size = 0;
4192
4193         // clear out the r_skinframe state
4194         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4195         memset(&r_skinframe, 0, sizeof(r_skinframe));
4196
4197         if (r_svbsp.nodes)
4198                 Mem_Free(r_svbsp.nodes);
4199         memset(&r_svbsp, 0, sizeof (r_svbsp));
4200         R_FreeTexturePool(&r_main_texturepool);
4201         loadingscreentexture = NULL;
4202         r_texture_blanknormalmap = NULL;
4203         r_texture_white = NULL;
4204         r_texture_grey128 = NULL;
4205         r_texture_black = NULL;
4206         r_texture_whitecube = NULL;
4207         r_texture_normalizationcube = NULL;
4208         r_texture_fogattenuation = NULL;
4209         r_texture_fogheighttexture = NULL;
4210         r_texture_gammaramps = NULL;
4211         r_texture_numcubemaps = 0;
4212         //r_texture_fogintensity = NULL;
4213         memset(&r_fb, 0, sizeof(r_fb));
4214         R_GLSL_Restart_f();
4215
4216         r_glsl_permutation = NULL;
4217         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4218         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4219         glslshaderstring = NULL;
4220 #ifdef SUPPORTD3D
4221         r_hlsl_permutation = NULL;
4222         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4223         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4224 #endif
4225         hlslshaderstring = NULL;
4226 }
4227
4228 static void gl_main_newmap(void)
4229 {
4230         // FIXME: move this code to client
4231         char *entities, entname[MAX_QPATH];
4232         if (r_qwskincache)
4233                 Mem_Free(r_qwskincache);
4234         r_qwskincache = NULL;
4235         r_qwskincache_size = 0;
4236         if (cl.worldmodel)
4237         {
4238                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4239                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4240                 {
4241                         CL_ParseEntityLump(entities);
4242                         Mem_Free(entities);
4243                         return;
4244                 }
4245                 if (cl.worldmodel->brush.entities)
4246                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4247         }
4248         R_Main_FreeViewCache();
4249
4250         R_FrameData_Reset();
4251         R_BufferData_Reset();
4252 }
4253
4254 void GL_Main_Init(void)
4255 {
4256         int i;
4257         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4258
4259         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4260         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4261         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4262         if (gamemode == GAME_NEHAHRA)
4263         {
4264                 Cvar_RegisterVariable (&gl_fogenable);
4265                 Cvar_RegisterVariable (&gl_fogdensity);
4266                 Cvar_RegisterVariable (&gl_fogred);
4267                 Cvar_RegisterVariable (&gl_foggreen);
4268                 Cvar_RegisterVariable (&gl_fogblue);
4269                 Cvar_RegisterVariable (&gl_fogstart);
4270                 Cvar_RegisterVariable (&gl_fogend);
4271                 Cvar_RegisterVariable (&gl_skyclip);
4272         }
4273         Cvar_RegisterVariable(&r_motionblur);
4274         Cvar_RegisterVariable(&r_damageblur);
4275         Cvar_RegisterVariable(&r_motionblur_averaging);
4276         Cvar_RegisterVariable(&r_motionblur_randomize);
4277         Cvar_RegisterVariable(&r_motionblur_minblur);
4278         Cvar_RegisterVariable(&r_motionblur_maxblur);
4279         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4280         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4281         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4282         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4283         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4284         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4285         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4286         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4287         Cvar_RegisterVariable(&r_equalize_entities_by);
4288         Cvar_RegisterVariable(&r_equalize_entities_to);
4289         Cvar_RegisterVariable(&r_depthfirst);
4290         Cvar_RegisterVariable(&r_useinfinitefarclip);
4291         Cvar_RegisterVariable(&r_farclip_base);
4292         Cvar_RegisterVariable(&r_farclip_world);
4293         Cvar_RegisterVariable(&r_nearclip);
4294         Cvar_RegisterVariable(&r_deformvertexes);
4295         Cvar_RegisterVariable(&r_transparent);
4296         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4297         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4298         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4299         Cvar_RegisterVariable(&r_showoverdraw);
4300         Cvar_RegisterVariable(&r_showbboxes);
4301         Cvar_RegisterVariable(&r_showsurfaces);
4302         Cvar_RegisterVariable(&r_showtris);
4303         Cvar_RegisterVariable(&r_shownormals);
4304         Cvar_RegisterVariable(&r_showlighting);
4305         Cvar_RegisterVariable(&r_showshadowvolumes);
4306         Cvar_RegisterVariable(&r_showcollisionbrushes);
4307         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4308         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4309         Cvar_RegisterVariable(&r_showdisabledepthtest);
4310         Cvar_RegisterVariable(&r_drawportals);
4311         Cvar_RegisterVariable(&r_drawentities);
4312         Cvar_RegisterVariable(&r_draw2d);
4313         Cvar_RegisterVariable(&r_drawworld);
4314         Cvar_RegisterVariable(&r_cullentities_trace);
4315         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4316         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4317         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4318         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4319         Cvar_RegisterVariable(&r_sortentities);
4320         Cvar_RegisterVariable(&r_drawviewmodel);
4321         Cvar_RegisterVariable(&r_drawexteriormodel);
4322         Cvar_RegisterVariable(&r_speeds);
4323         Cvar_RegisterVariable(&r_fullbrights);
4324         Cvar_RegisterVariable(&r_wateralpha);
4325         Cvar_RegisterVariable(&r_dynamic);
4326         Cvar_RegisterVariable(&r_fakelight);
4327         Cvar_RegisterVariable(&r_fakelight_intensity);
4328         Cvar_RegisterVariable(&r_fullbright);
4329         Cvar_RegisterVariable(&r_shadows);
4330         Cvar_RegisterVariable(&r_shadows_darken);
4331         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4332         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4333         Cvar_RegisterVariable(&r_shadows_throwdistance);
4334         Cvar_RegisterVariable(&r_shadows_throwdirection);
4335         Cvar_RegisterVariable(&r_shadows_focus);
4336         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4337         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4338         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4339         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4340         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4341         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4342         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4343         Cvar_RegisterVariable(&r_fog_exp2);
4344         Cvar_RegisterVariable(&r_fog_clear);
4345         Cvar_RegisterVariable(&r_drawfog);
4346         Cvar_RegisterVariable(&r_transparentdepthmasking);
4347         Cvar_RegisterVariable(&r_transparent_sortmindist);
4348         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4349         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4350         Cvar_RegisterVariable(&r_texture_dds_load);
4351         Cvar_RegisterVariable(&r_texture_dds_save);
4352         Cvar_RegisterVariable(&r_textureunits);
4353         Cvar_RegisterVariable(&gl_combine);
4354         Cvar_RegisterVariable(&r_usedepthtextures);
4355         Cvar_RegisterVariable(&r_viewfbo);
4356         Cvar_RegisterVariable(&r_viewscale);
4357         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4358         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4359         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4360         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4361         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4362         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4363         Cvar_RegisterVariable(&r_glsl);
4364         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4365         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4366         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4367         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4368         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4369         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4370         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4371         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4372         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4373         Cvar_RegisterVariable(&r_glsl_postprocess);
4374         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4375         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4376         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4377         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4378         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4379         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4380         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4381         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4382         Cvar_RegisterVariable(&r_celshading);
4383         Cvar_RegisterVariable(&r_celoutlines);
4384
4385         Cvar_RegisterVariable(&r_water);
4386         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4387         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4388         Cvar_RegisterVariable(&r_water_clippingplanebias);
4389         Cvar_RegisterVariable(&r_water_refractdistort);
4390         Cvar_RegisterVariable(&r_water_reflectdistort);
4391         Cvar_RegisterVariable(&r_water_scissormode);
4392         Cvar_RegisterVariable(&r_water_lowquality);
4393         Cvar_RegisterVariable(&r_water_hideplayer);
4394         Cvar_RegisterVariable(&r_water_fbo);
4395
4396         Cvar_RegisterVariable(&r_lerpsprites);
4397         Cvar_RegisterVariable(&r_lerpmodels);
4398         Cvar_RegisterVariable(&r_lerplightstyles);
4399         Cvar_RegisterVariable(&r_waterscroll);
4400         Cvar_RegisterVariable(&r_bloom);
4401         Cvar_RegisterVariable(&r_bloom_colorscale);
4402         Cvar_RegisterVariable(&r_bloom_brighten);
4403         Cvar_RegisterVariable(&r_bloom_blur);
4404         Cvar_RegisterVariable(&r_bloom_resolution);
4405         Cvar_RegisterVariable(&r_bloom_colorexponent);
4406         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4407         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4408         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4409         Cvar_RegisterVariable(&r_hdr_glowintensity);
4410         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4411         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4412         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4413         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4414         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4415         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4416         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4417         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4418         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4419         Cvar_RegisterVariable(&developer_texturelogging);
4420         Cvar_RegisterVariable(&gl_lightmaps);
4421         Cvar_RegisterVariable(&r_test);
4422         Cvar_RegisterVariable(&r_batch_multidraw);
4423         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4424         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4425         Cvar_RegisterVariable(&r_glsl_skeletal);
4426         Cvar_RegisterVariable(&r_glsl_saturation);
4427         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4428         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4429         Cvar_RegisterVariable(&r_framedatasize);
4430         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4431                 Cvar_RegisterVariable(&r_buffermegs[i]);
4432         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4433         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4434                 Cvar_SetValue("r_fullbrights", 0);
4435 #ifdef DP_MOBILETOUCH
4436         // GLES devices have terrible depth precision in general, so...
4437         Cvar_SetValueQuick(&r_nearclip, 4);
4438         Cvar_SetValueQuick(&r_farclip_base, 4096);
4439         Cvar_SetValueQuick(&r_farclip_world, 0);
4440         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4441 #endif
4442         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4443 }
4444
4445 void Render_Init(void)
4446 {
4447         gl_backend_init();
4448         R_Textures_Init();
4449         GL_Main_Init();
4450         Font_Init();
4451         GL_Draw_Init();
4452         R_Shadow_Init();
4453         R_Sky_Init();
4454         GL_Surf_Init();
4455         Sbar_Init();
4456         R_Particles_Init();
4457         R_Explosion_Init();
4458         R_LightningBeams_Init();
4459         Mod_RenderInit();
4460 }
4461
4462 /*
4463 ===============
4464 GL_Init
4465 ===============
4466 */
4467 #ifndef USE_GLES2
4468 extern char *ENGINE_EXTENSIONS;
4469 void GL_Init (void)
4470 {
4471         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4472         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4473         gl_version = (const char *)qglGetString(GL_VERSION);
4474         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4475
4476         if (!gl_extensions)
4477                 gl_extensions = "";
4478         if (!gl_platformextensions)
4479                 gl_platformextensions = "";
4480
4481         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4482         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4483         Con_Printf("GL_VERSION: %s\n", gl_version);
4484         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4485         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4486
4487         VID_CheckExtensions();
4488
4489         // LordHavoc: report supported extensions
4490 #ifdef CONFIG_MENU
4491         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4492 #else
4493         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4494 #endif
4495
4496         // clear to black (loading plaque will be seen over this)
4497         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4498 }
4499 #endif
4500
4501 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4502 {
4503         int i;
4504         mplane_t *p;
4505         if (r_trippy.integer)
4506                 return false;
4507         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4508         {
4509                 p = r_refdef.view.frustum + i;
4510                 switch(p->signbits)
4511                 {
4512                 default:
4513                 case 0:
4514                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4515                                 return true;
4516                         break;
4517                 case 1:
4518                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4519                                 return true;
4520                         break;
4521                 case 2:
4522                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4523                                 return true;
4524                         break;
4525                 case 3:
4526                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4527                                 return true;
4528                         break;
4529                 case 4:
4530                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4531                                 return true;
4532                         break;
4533                 case 5:
4534                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4535                                 return true;
4536                         break;
4537                 case 6:
4538                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4539                                 return true;
4540                         break;
4541                 case 7:
4542                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4543                                 return true;
4544                         break;
4545                 }
4546         }
4547         return false;
4548 }
4549
4550 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4551 {
4552         int i;
4553         const mplane_t *p;
4554         if (r_trippy.integer)
4555                 return false;
4556         for (i = 0;i < numplanes;i++)
4557         {
4558                 p = planes + i;
4559                 switch(p->signbits)
4560                 {
4561                 default:
4562                 case 0:
4563                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4564                                 return true;
4565                         break;
4566                 case 1:
4567                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4568                                 return true;
4569                         break;
4570                 case 2:
4571                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4572                                 return true;
4573                         break;
4574                 case 3:
4575                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4576                                 return true;
4577                         break;
4578                 case 4:
4579                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4580                                 return true;
4581                         break;
4582                 case 5:
4583                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4584                                 return true;
4585                         break;
4586                 case 6:
4587                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4588                                 return true;
4589                         break;
4590                 case 7:
4591                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4592                                 return true;
4593                         break;
4594                 }
4595         }
4596         return false;
4597 }
4598
4599 //==================================================================================
4600
4601 // LordHavoc: this stores temporary data used within the same frame
4602
4603 typedef struct r_framedata_mem_s
4604 {
4605         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4606         size_t size; // how much usable space
4607         size_t current; // how much space in use
4608         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4609         size_t wantedsize; // how much space was allocated
4610         unsigned char *data; // start of real data (16byte aligned)
4611 }
4612 r_framedata_mem_t;
4613
4614 static r_framedata_mem_t *r_framedata_mem;
4615
4616 void R_FrameData_Reset(void)
4617 {
4618         while (r_framedata_mem)
4619         {
4620                 r_framedata_mem_t *next = r_framedata_mem->purge;
4621                 Mem_Free(r_framedata_mem);
4622                 r_framedata_mem = next;
4623         }
4624 }
4625
4626 static void R_FrameData_Resize(qboolean mustgrow)
4627 {
4628         size_t wantedsize;
4629         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4630         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4631         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4632         {
4633                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4634                 newmem->wantedsize = wantedsize;
4635                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4636                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4637                 newmem->current = 0;
4638                 newmem->mark = 0;
4639                 newmem->purge = r_framedata_mem;
4640                 r_framedata_mem = newmem;
4641         }
4642 }
4643
4644 void R_FrameData_NewFrame(void)
4645 {
4646         R_FrameData_Resize(false);
4647         if (!r_framedata_mem)
4648                 return;
4649         // if we ran out of space on the last frame, free the old memory now
4650         while (r_framedata_mem->purge)
4651         {
4652                 // repeatedly remove the second item in the list, leaving only head
4653                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4654                 Mem_Free(r_framedata_mem->purge);
4655                 r_framedata_mem->purge = next;
4656         }
4657         // reset the current mem pointer
4658         r_framedata_mem->current = 0;
4659         r_framedata_mem->mark = 0;
4660 }
4661
4662 void *R_FrameData_Alloc(size_t size)
4663 {
4664         void *data;
4665         float newvalue;
4666
4667         // align to 16 byte boundary - the data pointer is already aligned, so we
4668         // only need to ensure the size of every allocation is also aligned
4669         size = (size + 15) & ~15;
4670
4671         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4672         {
4673                 // emergency - we ran out of space, allocate more memory
4674                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4675                 // this might not be a growing it, but we'll allocate another buffer every time
4676                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4677                 R_FrameData_Resize(true);
4678         }
4679
4680         data = r_framedata_mem->data + r_framedata_mem->current;
4681         r_framedata_mem->current += size;
4682
4683         // count the usage for stats
4684         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4685         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4686
4687         return (void *)data;
4688 }
4689
4690 void *R_FrameData_Store(size_t size, void *data)
4691 {
4692         void *d = R_FrameData_Alloc(size);
4693         if (d && data)
4694                 memcpy(d, data, size);
4695         return d;
4696 }
4697
4698 void R_FrameData_SetMark(void)
4699 {
4700         if (!r_framedata_mem)
4701                 return;
4702         r_framedata_mem->mark = r_framedata_mem->current;
4703 }
4704
4705 void R_FrameData_ReturnToMark(void)
4706 {
4707         if (!r_framedata_mem)
4708                 return;
4709         r_framedata_mem->current = r_framedata_mem->mark;
4710 }
4711
4712 //==================================================================================
4713
4714 // avoid reusing the same buffer objects on consecutive frames
4715 #define R_BUFFERDATA_CYCLE 3
4716
4717 typedef struct r_bufferdata_buffer_s
4718 {
4719         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4720         size_t size; // how much usable space
4721         size_t current; // how much space in use
4722         r_meshbuffer_t *buffer; // the buffer itself
4723 }
4724 r_bufferdata_buffer_t;
4725
4726 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4727 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4728
4729 /// frees all dynamic buffers
4730 void R_BufferData_Reset(void)
4731 {
4732         int cycle, type;
4733         r_bufferdata_buffer_t **p, *mem;
4734         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4735         {
4736                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4737                 {
4738                         // free all buffers
4739                         p = &r_bufferdata_buffer[cycle][type];
4740                         while (*p)
4741                         {
4742                                 mem = *p;
4743                                 *p = (*p)->purge;
4744                                 if (mem->buffer)
4745                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4746                                 Mem_Free(mem);
4747                         }
4748                 }
4749         }
4750 }
4751
4752 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4753 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4754 {
4755         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4756         size_t size;
4757         float newvalue = r_buffermegs[type].value;
4758
4759         // increase the cvar if we have to (but only if we already have a mem)
4760         if (mustgrow && mem)
4761                 newvalue *= 2.0f;
4762         newvalue = bound(0.25f, newvalue, 256.0f);
4763         while (newvalue * 1024*1024 < minsize)
4764                 newvalue *= 2.0f;
4765
4766         // clamp the cvar to valid range
4767         newvalue = bound(0.25f, newvalue, 256.0f);
4768         if (r_buffermegs[type].value != newvalue)
4769                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4770
4771         // calculate size in bytes
4772         size = (size_t)(newvalue * 1024*1024);
4773         size = bound(131072, size, 256*1024*1024);
4774
4775         // allocate a new buffer if the size is different (purge old one later)
4776         // or if we were told we must grow the buffer
4777         if (!mem || mem->size != size || mustgrow)
4778         {
4779                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4780                 mem->size = size;
4781                 mem->current = 0;
4782                 if (type == R_BUFFERDATA_VERTEX)
4783                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4784                 else if (type == R_BUFFERDATA_INDEX16)
4785                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4786                 else if (type == R_BUFFERDATA_INDEX32)
4787                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4788                 else if (type == R_BUFFERDATA_UNIFORM)
4789                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4790                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4791                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4792         }
4793 }
4794
4795 void R_BufferData_NewFrame(void)
4796 {
4797         int type;
4798         r_bufferdata_buffer_t **p, *mem;
4799         // cycle to the next frame's buffers
4800         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4801         // if we ran out of space on the last time we used these buffers, free the old memory now
4802         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4803         {
4804                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4805                 {
4806                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4807                         // free all but the head buffer, this is how we recycle obsolete
4808                         // buffers after they are no longer in use
4809                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4810                         while (*p)
4811                         {
4812                                 mem = *p;
4813                                 *p = (*p)->purge;
4814                                 if (mem->buffer)
4815                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4816                                 Mem_Free(mem);
4817                         }
4818                         // reset the current offset
4819                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4820                 }
4821         }
4822 }
4823
4824 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4825 {
4826         r_bufferdata_buffer_t *mem;
4827         int offset = 0;
4828         int padsize;
4829
4830         *returnbufferoffset = 0;
4831
4832         // align size to a byte boundary appropriate for the buffer type, this
4833         // makes all allocations have aligned start offsets
4834         if (type == R_BUFFERDATA_UNIFORM)
4835                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4836         else
4837                 padsize = (datasize + 15) & ~15;
4838
4839         // if we ran out of space in this buffer we must allocate a new one
4840         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)
4841                 R_BufferData_Resize(type, true, padsize);
4842
4843         // if the resize did not give us enough memory, fail
4844         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)
4845                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4846
4847         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4848         offset = (int)mem->current;
4849         mem->current += padsize;
4850
4851         // upload the data to the buffer at the chosen offset
4852         if (offset == 0)
4853                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4854         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4855
4856         // count the usage for stats
4857         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4858         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4859
4860         // return the buffer offset
4861         *returnbufferoffset = offset;
4862
4863         return mem->buffer;
4864 }
4865
4866 //==================================================================================
4867
4868 // LordHavoc: animcache originally written by Echon, rewritten since then
4869
4870 /**
4871  * Animation cache prevents re-generating mesh data for an animated model
4872  * multiple times in one frame for lighting, shadowing, reflections, etc.
4873  */
4874
4875 void R_AnimCache_Free(void)
4876 {
4877 }
4878
4879 void R_AnimCache_ClearCache(void)
4880 {
4881         int i;
4882         entity_render_t *ent;
4883
4884         for (i = 0;i < r_refdef.scene.numentities;i++)
4885         {
4886                 ent = r_refdef.scene.entities[i];
4887                 ent->animcache_vertex3f = NULL;
4888                 ent->animcache_vertex3f_vertexbuffer = NULL;
4889                 ent->animcache_vertex3f_bufferoffset = 0;
4890                 ent->animcache_normal3f = NULL;
4891                 ent->animcache_normal3f_vertexbuffer = NULL;
4892                 ent->animcache_normal3f_bufferoffset = 0;
4893                 ent->animcache_svector3f = NULL;
4894                 ent->animcache_svector3f_vertexbuffer = NULL;
4895                 ent->animcache_svector3f_bufferoffset = 0;
4896                 ent->animcache_tvector3f = NULL;
4897                 ent->animcache_tvector3f_vertexbuffer = NULL;
4898                 ent->animcache_tvector3f_bufferoffset = 0;
4899                 ent->animcache_vertexmesh = NULL;
4900                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4901                 ent->animcache_vertexmesh_bufferoffset = 0;
4902                 ent->animcache_skeletaltransform3x4 = NULL;
4903                 ent->animcache_skeletaltransform3x4buffer = NULL;
4904                 ent->animcache_skeletaltransform3x4offset = 0;
4905                 ent->animcache_skeletaltransform3x4size = 0;
4906         }
4907 }
4908
4909 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4910 {
4911         int i;
4912
4913         // check if we need the meshbuffers
4914         if (!vid.useinterleavedarrays)
4915                 return;
4916
4917         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4918                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4919         // TODO: upload vertexbuffer?
4920         if (ent->animcache_vertexmesh)
4921         {
4922                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4923                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4924                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4925                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4926                 for (i = 0;i < numvertices;i++)
4927                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4928                 if (ent->animcache_svector3f)
4929                         for (i = 0;i < numvertices;i++)
4930                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4931                 if (ent->animcache_tvector3f)
4932                         for (i = 0;i < numvertices;i++)
4933                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4934                 if (ent->animcache_normal3f)
4935                         for (i = 0;i < numvertices;i++)
4936                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4937         }
4938 }
4939
4940 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4941 {
4942         dp_model_t *model = ent->model;
4943         int numvertices;
4944
4945         // see if this ent is worth caching
4946         if (!model || !model->Draw || !model->AnimateVertices)
4947                 return false;
4948         // nothing to cache if it contains no animations and has no skeleton
4949         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4950                 return false;
4951         // see if it is already cached for gpuskeletal
4952         if (ent->animcache_skeletaltransform3x4)
4953                 return false;
4954         // see if it is already cached as a mesh
4955         if (ent->animcache_vertex3f)
4956         {
4957                 // check if we need to add normals or tangents
4958                 if (ent->animcache_normal3f)
4959                         wantnormals = false;
4960                 if (ent->animcache_svector3f)
4961                         wanttangents = false;
4962                 if (!wantnormals && !wanttangents)
4963                         return false;
4964         }
4965
4966         // check which kind of cache we need to generate
4967         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4968         {
4969                 // cache the skeleton so the vertex shader can use it
4970                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4971                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4972                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4973                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4974                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4975                 // note: this can fail if the buffer is at the grow limit
4976                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4977                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4978         }
4979         else if (ent->animcache_vertex3f)
4980         {
4981                 // mesh was already cached but we may need to add normals/tangents
4982                 // (this only happens with multiple views, reflections, cameras, etc)
4983                 if (wantnormals || wanttangents)
4984                 {
4985                         numvertices = model->surfmesh.num_vertices;
4986                         if (wantnormals)
4987                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4988                         if (wanttangents)
4989                         {
4990                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4991                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4992                         }
4993                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4994                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4995                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4996                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4997                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4998                 }
4999         }
5000         else
5001         {
5002                 // generate mesh cache
5003                 numvertices = model->surfmesh.num_vertices;
5004                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5005                 if (wantnormals)
5006                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5007                 if (wanttangents)
5008                 {
5009                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5010                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5011                 }
5012                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5013                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5014                 if (wantnormals || wanttangents)
5015                 {
5016                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5017                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5018                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5019                 }
5020                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5021                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5022                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5023         }
5024         return true;
5025 }
5026
5027 void R_AnimCache_CacheVisibleEntities(void)
5028 {
5029         int i;
5030         qboolean wantnormals = true;
5031         qboolean wanttangents = !r_showsurfaces.integer;
5032
5033         switch(vid.renderpath)
5034         {
5035         case RENDERPATH_GL20:
5036         case RENDERPATH_D3D9:
5037         case RENDERPATH_D3D10:
5038         case RENDERPATH_D3D11:
5039         case RENDERPATH_GLES2:
5040                 break;
5041         case RENDERPATH_GL11:
5042         case RENDERPATH_GL13:
5043         case RENDERPATH_GLES1:
5044                 wanttangents = false;
5045                 break;
5046         case RENDERPATH_SOFT:
5047                 break;
5048         }
5049
5050         if (r_shownormals.integer)
5051                 wanttangents = wantnormals = true;
5052
5053         // TODO: thread this
5054         // NOTE: R_PrepareRTLights() also caches entities
5055
5056         for (i = 0;i < r_refdef.scene.numentities;i++)
5057                 if (r_refdef.viewcache.entityvisible[i])
5058                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5059 }
5060
5061 //==================================================================================
5062
5063 extern cvar_t r_overheadsprites_pushback;
5064
5065 static void R_View_UpdateEntityLighting (void)
5066 {
5067         int i;
5068         entity_render_t *ent;
5069         vec3_t tempdiffusenormal, avg;
5070         vec_t f, fa, fd, fdd;
5071         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5072
5073         for (i = 0;i < r_refdef.scene.numentities;i++)
5074         {
5075                 ent = r_refdef.scene.entities[i];
5076
5077                 // skip unseen models
5078                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5079                         continue;
5080
5081                 // skip bsp models
5082                 if (ent->model && ent->model == cl.worldmodel)
5083                 {
5084                         // TODO: use modellight for r_ambient settings on world?
5085                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5086                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5087                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5088                         continue;
5089                 }
5090                 
5091                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5092                 {
5093                         // aleady updated by CSQC
5094                         // TODO: force modellight on BSP models in this case?
5095                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5096                 }
5097                 else
5098                 {
5099                         // fetch the lighting from the worldmodel data
5100                         VectorClear(ent->modellight_ambient);
5101                         VectorClear(ent->modellight_diffuse);
5102                         VectorClear(tempdiffusenormal);
5103                         if (ent->flags & RENDER_LIGHT)
5104                         {
5105                                 vec3_t org;
5106                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5107
5108                                 // complete lightning for lit sprites
5109                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5110                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5111                                 {
5112                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5113                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5114                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5115                                 }
5116                                 else
5117                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5118
5119                                 if(ent->flags & RENDER_EQUALIZE)
5120                                 {
5121                                         // first fix up ambient lighting...
5122                                         if(r_equalize_entities_minambient.value > 0)
5123                                         {
5124                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5125                                                 if(fd > 0)
5126                                                 {
5127                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5128                                                         if(fa < r_equalize_entities_minambient.value * fd)
5129                                                         {
5130                                                                 // solve:
5131                                                                 //   fa'/fd' = minambient
5132                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5133                                                                 //   ...
5134                                                                 //   fa' = fd' * minambient
5135                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5136                                                                 //   ...
5137                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5138                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5139                                                                 //   ...
5140                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5141                                                                 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
5142                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5143                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5144                                                         }
5145                                                 }
5146                                         }
5147
5148                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5149                                         {
5150                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5151                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5152                                                 f = fa + 0.25 * fd;
5153                                                 if(f > 0)
5154                                                 {
5155                                                         // adjust brightness and saturation to target
5156                                                         avg[0] = avg[1] = avg[2] = fa / f;
5157                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5158                                                         avg[0] = avg[1] = avg[2] = fd / f;
5159                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5160                                                 }
5161                                         }
5162                                 }
5163                         }
5164                         else // highly rare
5165                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5166                 }
5167
5168                 // move the light direction into modelspace coordinates for lighting code
5169                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5170                 if(VectorLength2(ent->modellight_lightdir) == 0)
5171                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5172                 VectorNormalize(ent->modellight_lightdir);
5173         }
5174 }
5175
5176 #define MAX_LINEOFSIGHTTRACES 64
5177
5178 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5179 {
5180         int i;
5181         vec3_t boxmins, boxmaxs;
5182         vec3_t start;
5183         vec3_t end;
5184         dp_model_t *model = r_refdef.scene.worldmodel;
5185
5186         if (!model || !model->brush.TraceLineOfSight)
5187                 return true;
5188
5189         // expand the box a little
5190         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5191         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5192         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5193         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5194         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5195         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5196
5197         // return true if eye is inside enlarged box
5198         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5199                 return true;
5200
5201         // try center
5202         VectorCopy(eye, start);
5203         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5204         if (model->brush.TraceLineOfSight(model, start, end))
5205                 return true;
5206
5207         // try various random positions
5208         for (i = 0;i < numsamples;i++)
5209         {
5210                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5211                 if (model->brush.TraceLineOfSight(model, start, end))
5212                         return true;
5213         }
5214
5215         return false;
5216 }
5217
5218
5219 static void R_View_UpdateEntityVisible (void)
5220 {
5221         int i;
5222         int renderimask;
5223         int samples;
5224         entity_render_t *ent;
5225
5226         if (r_refdef.envmap || r_fb.water.hideplayer)
5227                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5228         else if (chase_active.integer || r_fb.water.renderingscene)
5229                 renderimask = RENDER_VIEWMODEL;
5230         else
5231                 renderimask = RENDER_EXTERIORMODEL;
5232         if (!r_drawviewmodel.integer)
5233                 renderimask |= RENDER_VIEWMODEL;
5234         if (!r_drawexteriormodel.integer)
5235                 renderimask |= RENDER_EXTERIORMODEL;
5236         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5237         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5238         {
5239                 // worldmodel can check visibility
5240                 for (i = 0;i < r_refdef.scene.numentities;i++)
5241                 {
5242                         ent = r_refdef.scene.entities[i];
5243                         if (!(ent->flags & renderimask))
5244                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
5245                         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))
5246                                 r_refdef.viewcache.entityvisible[i] = true;
5247                 }
5248         }
5249         else
5250         {
5251                 // no worldmodel or it can't check visibility
5252                 for (i = 0;i < r_refdef.scene.numentities;i++)
5253                 {
5254                         ent = r_refdef.scene.entities[i];
5255                         if (!(ent->flags & renderimask))
5256                         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)))
5257                                 r_refdef.viewcache.entityvisible[i] = true;
5258                 }
5259         }
5260         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5261                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5262         {
5263                 for (i = 0;i < r_refdef.scene.numentities;i++)
5264                 {
5265                         if (!r_refdef.viewcache.entityvisible[i])
5266                                 continue;
5267                         ent = r_refdef.scene.entities[i];
5268                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5269                         {
5270                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5271                                 if (samples < 0)
5272                                         continue; // temp entities do pvs only
5273                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5274                                         ent->last_trace_visibility = realtime;
5275                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5276                                         r_refdef.viewcache.entityvisible[i] = 0;
5277                         }
5278                 }
5279         }
5280 }
5281
5282 /// only used if skyrendermasked, and normally returns false
5283 static int R_DrawBrushModelsSky (void)
5284 {
5285         int i, sky;
5286         entity_render_t *ent;
5287
5288         sky = false;
5289         for (i = 0;i < r_refdef.scene.numentities;i++)
5290         {
5291                 if (!r_refdef.viewcache.entityvisible[i])
5292                         continue;
5293                 ent = r_refdef.scene.entities[i];
5294                 if (!ent->model || !ent->model->DrawSky)
5295                         continue;
5296                 ent->model->DrawSky(ent);
5297                 sky = true;
5298         }
5299         return sky;
5300 }
5301
5302 static void R_DrawNoModel(entity_render_t *ent);
5303 static void R_DrawModels(void)
5304 {
5305         int i;
5306         entity_render_t *ent;
5307
5308         for (i = 0;i < r_refdef.scene.numentities;i++)
5309         {
5310                 if (!r_refdef.viewcache.entityvisible[i])
5311                         continue;
5312                 ent = r_refdef.scene.entities[i];
5313                 r_refdef.stats[r_stat_entities]++;
5314                 /*
5315                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5316                 {
5317                         vec3_t f, l, u, o;
5318                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5319                         Con_Printf("R_DrawModels\n");
5320                         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]);
5321                         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);
5322                         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);
5323                 }
5324                 */
5325                 if (ent->model && ent->model->Draw != NULL)
5326                         ent->model->Draw(ent);
5327                 else
5328                         R_DrawNoModel(ent);
5329         }
5330 }
5331
5332 static void R_DrawModelsDepth(void)
5333 {
5334         int i;
5335         entity_render_t *ent;
5336
5337         for (i = 0;i < r_refdef.scene.numentities;i++)
5338         {
5339                 if (!r_refdef.viewcache.entityvisible[i])
5340                         continue;
5341                 ent = r_refdef.scene.entities[i];
5342                 if (ent->model && ent->model->DrawDepth != NULL)
5343                         ent->model->DrawDepth(ent);
5344         }
5345 }
5346
5347 static void R_DrawModelsDebug(void)
5348 {
5349         int i;
5350         entity_render_t *ent;
5351
5352         for (i = 0;i < r_refdef.scene.numentities;i++)
5353         {
5354                 if (!r_refdef.viewcache.entityvisible[i])
5355                         continue;
5356                 ent = r_refdef.scene.entities[i];
5357                 if (ent->model && ent->model->DrawDebug != NULL)
5358                         ent->model->DrawDebug(ent);
5359         }
5360 }
5361
5362 static void R_DrawModelsAddWaterPlanes(void)
5363 {
5364         int i;
5365         entity_render_t *ent;
5366
5367         for (i = 0;i < r_refdef.scene.numentities;i++)
5368         {
5369                 if (!r_refdef.viewcache.entityvisible[i])
5370                         continue;
5371                 ent = r_refdef.scene.entities[i];
5372                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5373                         ent->model->DrawAddWaterPlanes(ent);
5374         }
5375 }
5376
5377 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}};
5378
5379 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5380 {
5381         if (r_hdr_irisadaptation.integer)
5382         {
5383                 vec3_t p;
5384                 vec3_t ambient;
5385                 vec3_t diffuse;
5386                 vec3_t diffusenormal;
5387                 vec3_t forward;
5388                 vec_t brightness = 0.0f;
5389                 vec_t goal;
5390                 vec_t current;
5391                 vec_t d;
5392                 int c;
5393                 VectorCopy(r_refdef.view.forward, forward);
5394                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5395                 {
5396                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5397                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5398                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5399                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5400                         d = DotProduct(forward, diffusenormal);
5401                         brightness += VectorLength(ambient);
5402                         if (d > 0)
5403                                 brightness += d * VectorLength(diffuse);
5404                 }
5405                 brightness *= 1.0f / c;
5406                 brightness += 0.00001f; // make sure it's never zero
5407                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5408                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5409                 current = r_hdr_irisadaptation_value.value;
5410                 if (current < goal)
5411                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5412                 else if (current > goal)
5413                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5414                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5415                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5416         }
5417         else if (r_hdr_irisadaptation_value.value != 1.0f)
5418                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5419 }
5420
5421 static void R_View_SetFrustum(const int *scissor)
5422 {
5423         int i;
5424         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5425         vec3_t forward, left, up, origin, v;
5426
5427         if(scissor)
5428         {
5429                 // flipped x coordinates (because x points left here)
5430                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5431                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5432
5433                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5434                 switch(vid.renderpath)
5435                 {
5436                         case RENDERPATH_D3D9:
5437                         case RENDERPATH_D3D10:
5438                         case RENDERPATH_D3D11:
5439                                 // non-flipped y coordinates
5440                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5441                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5442                                 break;
5443                         case RENDERPATH_SOFT:
5444                         case RENDERPATH_GL11:
5445                         case RENDERPATH_GL13:
5446                         case RENDERPATH_GL20:
5447                         case RENDERPATH_GLES1:
5448                         case RENDERPATH_GLES2:
5449                                 // non-flipped y coordinates
5450                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5451                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5452                                 break;
5453                 }
5454         }
5455
5456         // we can't trust r_refdef.view.forward and friends in reflected scenes
5457         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5458
5459 #if 0
5460         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5461         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5462         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5463         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5464         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5465         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5466         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5467         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5468         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5469         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5470         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5471         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5472 #endif
5473
5474 #if 0
5475         zNear = r_refdef.nearclip;
5476         nudge = 1.0 - 1.0 / (1<<23);
5477         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5478         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5479         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5480         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5481         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5482         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5483         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5484         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5485 #endif
5486
5487
5488
5489 #if 0
5490         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5491         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5492         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5493         r_refdef.view.frustum[0].dist = m[15] - m[12];
5494
5495         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5496         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5497         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5498         r_refdef.view.frustum[1].dist = m[15] + m[12];
5499
5500         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5501         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5502         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5503         r_refdef.view.frustum[2].dist = m[15] - m[13];
5504
5505         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5506         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5507         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5508         r_refdef.view.frustum[3].dist = m[15] + m[13];
5509
5510         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5511         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5512         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5513         r_refdef.view.frustum[4].dist = m[15] - m[14];
5514
5515         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5516         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5517         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5518         r_refdef.view.frustum[5].dist = m[15] + m[14];
5519 #endif
5520
5521         if (r_refdef.view.useperspective)
5522         {
5523                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5524                 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]);
5525                 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]);
5526                 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]);
5527                 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]);
5528
5529                 // then the normals from the corners relative to origin
5530                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5531                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5532                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5533                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5534
5535                 // in a NORMAL view, forward cross left == up
5536                 // in a REFLECTED view, forward cross left == down
5537                 // so our cross products above need to be adjusted for a left handed coordinate system
5538                 CrossProduct(forward, left, v);
5539                 if(DotProduct(v, up) < 0)
5540                 {
5541                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5542                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5543                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5544                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5545                 }
5546
5547                 // Leaving those out was a mistake, those were in the old code, and they
5548                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5549                 // I couldn't reproduce it after adding those normalizations. --blub
5550                 VectorNormalize(r_refdef.view.frustum[0].normal);
5551                 VectorNormalize(r_refdef.view.frustum[1].normal);
5552                 VectorNormalize(r_refdef.view.frustum[2].normal);
5553                 VectorNormalize(r_refdef.view.frustum[3].normal);
5554
5555                 // make the corners absolute
5556                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5557                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5558                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5559                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5560
5561                 // one more normal
5562                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5563
5564                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5565                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5566                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5567                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5568                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5569         }
5570         else
5571         {
5572                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5573                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5574                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5575                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5576                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5577                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5578                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5579                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5580                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5581                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5582         }
5583         r_refdef.view.numfrustumplanes = 5;
5584
5585         if (r_refdef.view.useclipplane)
5586         {
5587                 r_refdef.view.numfrustumplanes = 6;
5588                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5589         }
5590
5591         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5592                 PlaneClassify(r_refdef.view.frustum + i);
5593
5594         // LordHavoc: note to all quake engine coders, Quake had a special case
5595         // for 90 degrees which assumed a square view (wrong), so I removed it,
5596         // Quake2 has it disabled as well.
5597
5598         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5599         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5600         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5601         //PlaneClassify(&frustum[0]);
5602
5603         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5604         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5605         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5606         //PlaneClassify(&frustum[1]);
5607
5608         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5609         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5610         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5611         //PlaneClassify(&frustum[2]);
5612
5613         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5614         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5615         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5616         //PlaneClassify(&frustum[3]);
5617
5618         // nearclip plane
5619         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5620         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5621         //PlaneClassify(&frustum[4]);
5622 }
5623
5624 static void R_View_UpdateWithScissor(const int *myscissor)
5625 {
5626         R_Main_ResizeViewCache();
5627         R_View_SetFrustum(myscissor);
5628         R_View_WorldVisibility(r_refdef.view.useclipplane);
5629         R_View_UpdateEntityVisible();
5630         R_View_UpdateEntityLighting();
5631 }
5632
5633 static void R_View_Update(void)
5634 {
5635         R_Main_ResizeViewCache();
5636         R_View_SetFrustum(NULL);
5637         R_View_WorldVisibility(r_refdef.view.useclipplane);
5638         R_View_UpdateEntityVisible();
5639         R_View_UpdateEntityLighting();
5640 }
5641
5642 float viewscalefpsadjusted = 1.0f;
5643
5644 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5645 {
5646         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5647         scale = bound(0.03125f, scale, 1.0f);
5648         *outwidth = (int)ceil(width * scale);
5649         *outheight = (int)ceil(height * scale);
5650 }
5651
5652 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5653 {
5654         const float *customclipplane = NULL;
5655         float plane[4];
5656         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5657         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5658         {
5659                 // LordHavoc: couldn't figure out how to make this approach the
5660                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5661                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5662                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5663                         dist = r_refdef.view.clipplane.dist;
5664                 plane[0] = r_refdef.view.clipplane.normal[0];
5665                 plane[1] = r_refdef.view.clipplane.normal[1];
5666                 plane[2] = r_refdef.view.clipplane.normal[2];
5667                 plane[3] = -dist;
5668                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5669         }
5670
5671         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5672         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5673
5674         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5675         if (!r_refdef.view.useperspective)
5676                 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);
5677         else if (vid.stencil && r_useinfinitefarclip.integer)
5678                 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);
5679         else
5680                 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);
5681         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5682         R_SetViewport(&r_refdef.view.viewport);
5683         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5684         {
5685                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5686                 float screenplane[4];
5687                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5688                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5689                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5690                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5691                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5692         }
5693 }
5694
5695 void R_EntityMatrix(const matrix4x4_t *matrix)
5696 {
5697         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5698         {
5699                 gl_modelmatrixchanged = false;
5700                 gl_modelmatrix = *matrix;
5701                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5702                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5703                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5704                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5705                 CHECKGLERROR
5706                 switch(vid.renderpath)
5707                 {
5708                 case RENDERPATH_D3D9:
5709 #ifdef SUPPORTD3D
5710                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5711                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5712 #endif
5713                         break;
5714                 case RENDERPATH_D3D10:
5715                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5716                         break;
5717                 case RENDERPATH_D3D11:
5718                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5719                         break;
5720                 case RENDERPATH_GL11:
5721                 case RENDERPATH_GL13:
5722                 case RENDERPATH_GLES1:
5723 #ifndef USE_GLES2
5724                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5725 #endif
5726                         break;
5727                 case RENDERPATH_SOFT:
5728                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5729                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5730                         break;
5731                 case RENDERPATH_GL20:
5732                 case RENDERPATH_GLES2:
5733                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5734                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5735                         break;
5736                 }
5737         }
5738 }
5739
5740 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5741 {
5742         r_viewport_t viewport;
5743
5744         CHECKGLERROR
5745
5746         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5747         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);
5748         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5749         R_SetViewport(&viewport);
5750         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5751         GL_Color(1, 1, 1, 1);
5752         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5753         GL_BlendFunc(GL_ONE, GL_ZERO);
5754         GL_ScissorTest(false);
5755         GL_DepthMask(false);
5756         GL_DepthRange(0, 1);
5757         GL_DepthTest(false);
5758         GL_DepthFunc(GL_LEQUAL);
5759         R_EntityMatrix(&identitymatrix);
5760         R_Mesh_ResetTextureState();
5761         GL_PolygonOffset(0, 0);
5762         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5763         switch(vid.renderpath)
5764         {
5765         case RENDERPATH_GL11:
5766         case RENDERPATH_GL13:
5767         case RENDERPATH_GL20:
5768         case RENDERPATH_GLES1:
5769         case RENDERPATH_GLES2:
5770                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5771                 break;
5772         case RENDERPATH_D3D9:
5773         case RENDERPATH_D3D10:
5774         case RENDERPATH_D3D11:
5775         case RENDERPATH_SOFT:
5776                 break;
5777         }
5778         GL_CullFace(GL_NONE);
5779
5780         CHECKGLERROR
5781 }
5782
5783 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5784 {
5785         DrawQ_Finish();
5786
5787         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5788 }
5789
5790 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5791 {
5792         DrawQ_Finish();
5793
5794         R_SetupView(true, fbo, depthtexture, colortexture);
5795         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5796         GL_Color(1, 1, 1, 1);
5797         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5798         GL_BlendFunc(GL_ONE, GL_ZERO);
5799         GL_ScissorTest(true);
5800         GL_DepthMask(true);
5801         GL_DepthRange(0, 1);
5802         GL_DepthTest(true);
5803         GL_DepthFunc(GL_LEQUAL);
5804         R_EntityMatrix(&identitymatrix);
5805         R_Mesh_ResetTextureState();
5806         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5807         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5808         switch(vid.renderpath)
5809         {
5810         case RENDERPATH_GL11:
5811         case RENDERPATH_GL13:
5812         case RENDERPATH_GL20:
5813         case RENDERPATH_GLES1:
5814         case RENDERPATH_GLES2:
5815                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5816                 break;
5817         case RENDERPATH_D3D9:
5818         case RENDERPATH_D3D10:
5819         case RENDERPATH_D3D11:
5820         case RENDERPATH_SOFT:
5821                 break;
5822         }
5823         GL_CullFace(r_refdef.view.cullface_back);
5824 }
5825
5826 /*
5827 ================
5828 R_RenderView_UpdateViewVectors
5829 ================
5830 */
5831 void R_RenderView_UpdateViewVectors(void)
5832 {
5833         // break apart the view matrix into vectors for various purposes
5834         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5835         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5836         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5837         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5838         // make an inverted copy of the view matrix for tracking sprites
5839         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5840 }
5841
5842 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5843 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5844
5845 static void R_Water_StartFrame(void)
5846 {
5847         int i;
5848         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5849         r_waterstate_waterplane_t *p;
5850         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;
5851
5852         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5853                 return;
5854
5855         switch(vid.renderpath)
5856         {
5857         case RENDERPATH_GL20:
5858         case RENDERPATH_D3D9:
5859         case RENDERPATH_D3D10:
5860         case RENDERPATH_D3D11:
5861         case RENDERPATH_SOFT:
5862         case RENDERPATH_GLES2:
5863                 break;
5864         case RENDERPATH_GL11:
5865         case RENDERPATH_GL13:
5866         case RENDERPATH_GLES1:
5867                 return;
5868         }
5869
5870         // set waterwidth and waterheight to the water resolution that will be
5871         // used (often less than the screen resolution for faster rendering)
5872         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5873
5874         // calculate desired texture sizes
5875         // can't use water if the card does not support the texture size
5876         if (!r_water.integer || r_showsurfaces.integer)
5877                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5878         else if (vid.support.arb_texture_non_power_of_two)
5879         {
5880                 texturewidth = waterwidth;
5881                 textureheight = waterheight;
5882                 camerawidth = waterwidth;
5883                 cameraheight = waterheight;
5884         }
5885         else
5886         {
5887                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5888                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5889                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5890                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5891         }
5892
5893         // allocate textures as needed
5894         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))
5895         {
5896                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5897                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5898                 {
5899                         if (p->texture_refraction)
5900                                 R_FreeTexture(p->texture_refraction);
5901                         p->texture_refraction = NULL;
5902                         if (p->fbo_refraction)
5903                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5904                         p->fbo_refraction = 0;
5905                         if (p->texture_reflection)
5906                                 R_FreeTexture(p->texture_reflection);
5907                         p->texture_reflection = NULL;
5908                         if (p->fbo_reflection)
5909                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5910                         p->fbo_reflection = 0;
5911                         if (p->texture_camera)
5912                                 R_FreeTexture(p->texture_camera);
5913                         p->texture_camera = NULL;
5914                         if (p->fbo_camera)
5915                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5916                         p->fbo_camera = 0;
5917                 }
5918                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5919                 r_fb.water.texturewidth = texturewidth;
5920                 r_fb.water.textureheight = textureheight;
5921                 r_fb.water.camerawidth = camerawidth;
5922                 r_fb.water.cameraheight = cameraheight;
5923         }
5924
5925         if (r_fb.water.texturewidth)
5926         {
5927                 int scaledwidth, scaledheight;
5928
5929                 r_fb.water.enabled = true;
5930
5931                 // water resolution is usually reduced
5932                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5933                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5934                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5935
5936                 // set up variables that will be used in shader setup
5937                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5938                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5939                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5940                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5941         }
5942
5943         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5944         r_fb.water.numwaterplanes = 0;
5945 }
5946
5947 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5948 {
5949         int planeindex, bestplaneindex, vertexindex;
5950         vec3_t mins, maxs, normal, center, v, n;
5951         vec_t planescore, bestplanescore;
5952         mplane_t plane;
5953         r_waterstate_waterplane_t *p;
5954         texture_t *t = R_GetCurrentTexture(surface->texture);
5955
5956         rsurface.texture = t;
5957         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5958         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5959         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5960                 return;
5961         // average the vertex normals, find the surface bounds (after deformvertexes)
5962         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5963         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5964         VectorCopy(n, normal);
5965         VectorCopy(v, mins);
5966         VectorCopy(v, maxs);
5967         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5968         {
5969                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5970                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5971                 VectorAdd(normal, n, normal);
5972                 mins[0] = min(mins[0], v[0]);
5973                 mins[1] = min(mins[1], v[1]);
5974                 mins[2] = min(mins[2], v[2]);
5975                 maxs[0] = max(maxs[0], v[0]);
5976                 maxs[1] = max(maxs[1], v[1]);
5977                 maxs[2] = max(maxs[2], v[2]);
5978         }
5979         VectorNormalize(normal);
5980         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5981
5982         VectorCopy(normal, plane.normal);
5983         VectorNormalize(plane.normal);
5984         plane.dist = DotProduct(center, plane.normal);
5985         PlaneClassify(&plane);
5986         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5987         {
5988                 // skip backfaces (except if nocullface is set)
5989 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5990 //                      return;
5991                 VectorNegate(plane.normal, plane.normal);
5992                 plane.dist *= -1;
5993                 PlaneClassify(&plane);
5994         }
5995
5996
5997         // find a matching plane if there is one
5998         bestplaneindex = -1;
5999         bestplanescore = 1048576.0f;
6000         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6001         {
6002                 if(p->camera_entity == t->camera_entity)
6003                 {
6004                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6005                         if (bestplaneindex < 0 || bestplanescore > planescore)
6006                         {
6007                                 bestplaneindex = planeindex;
6008                                 bestplanescore = planescore;
6009                         }
6010                 }
6011         }
6012         planeindex = bestplaneindex;
6013
6014         // if this surface does not fit any known plane rendered this frame, add one
6015         if (planeindex < 0 || bestplanescore > 0.001f)
6016         {
6017                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6018                 {
6019                         // store the new plane
6020                         planeindex = r_fb.water.numwaterplanes++;
6021                         p = r_fb.water.waterplanes + planeindex;
6022                         p->plane = plane;
6023                         // clear materialflags and pvs
6024                         p->materialflags = 0;
6025                         p->pvsvalid = false;
6026                         p->camera_entity = t->camera_entity;
6027                         VectorCopy(mins, p->mins);
6028                         VectorCopy(maxs, p->maxs);
6029                 }
6030                 else
6031                 {
6032                         // We're totally screwed.
6033                         return;
6034                 }
6035         }
6036         else
6037         {
6038                 // merge mins/maxs when we're adding this surface to the plane
6039                 p = r_fb.water.waterplanes + planeindex;
6040                 p->mins[0] = min(p->mins[0], mins[0]);
6041                 p->mins[1] = min(p->mins[1], mins[1]);
6042                 p->mins[2] = min(p->mins[2], mins[2]);
6043                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6044                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6045                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6046         }
6047         // merge this surface's materialflags into the waterplane
6048         p->materialflags |= t->currentmaterialflags;
6049         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6050         {
6051                 // merge this surface's PVS into the waterplane
6052                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6053                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6054                 {
6055                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6056                         p->pvsvalid = true;
6057                 }
6058         }
6059 }
6060
6061 extern cvar_t r_drawparticles;
6062 extern cvar_t r_drawdecals;
6063
6064 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6065 {
6066         int myscissor[4];
6067         r_refdef_view_t originalview;
6068         r_refdef_view_t myview;
6069         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;
6070         r_waterstate_waterplane_t *p;
6071         vec3_t visorigin;
6072         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;
6073         char vabuf[1024];
6074
6075         originalview = r_refdef.view;
6076
6077         // lowquality hack, temporarily shut down some cvars and restore afterwards
6078         qualityreduction = r_water_lowquality.integer;
6079         if (qualityreduction > 0)
6080         {
6081                 if (qualityreduction >= 1)
6082                 {
6083                         old_r_shadows = r_shadows.integer;
6084                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6085                         old_r_dlight = r_shadow_realtime_dlight.integer;
6086                         Cvar_SetValueQuick(&r_shadows, 0);
6087                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6088                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6089                 }
6090                 if (qualityreduction >= 2)
6091                 {
6092                         old_r_dynamic = r_dynamic.integer;
6093                         old_r_particles = r_drawparticles.integer;
6094                         old_r_decals = r_drawdecals.integer;
6095                         Cvar_SetValueQuick(&r_dynamic, 0);
6096                         Cvar_SetValueQuick(&r_drawparticles, 0);
6097                         Cvar_SetValueQuick(&r_drawdecals, 0);
6098                 }
6099         }
6100
6101         // make sure enough textures are allocated
6102         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6103         {
6104                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6105                         continue;
6106                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6107                 {
6108                         if (!p->texture_refraction)
6109                                 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);
6110                         if (!p->texture_refraction)
6111                                 goto error;
6112                         if (usewaterfbo)
6113                         {
6114                                 if (r_fb.water.depthtexture == NULL)
6115                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6116                                 if (p->fbo_refraction == 0)
6117                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6118                         }
6119                 }
6120                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6121                 {
6122                         if (!p->texture_camera)
6123                                 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);
6124                         if (!p->texture_camera)
6125                                 goto error;
6126                         if (usewaterfbo)
6127                         {
6128                                 if (r_fb.water.depthtexture == NULL)
6129                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6130                                 if (p->fbo_camera == 0)
6131                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6132                         }
6133                 }
6134
6135                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6136                 {
6137                         if (!p->texture_reflection)
6138                                 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);
6139                         if (!p->texture_reflection)
6140                                 goto error;
6141                         if (usewaterfbo)
6142                         {
6143                                 if (r_fb.water.depthtexture == NULL)
6144                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6145                                 if (p->fbo_reflection == 0)
6146                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6147                         }
6148                 }
6149         }
6150
6151         // render views
6152         r_refdef.view = originalview;
6153         r_refdef.view.showdebug = false;
6154         r_refdef.view.width = r_fb.water.waterwidth;
6155         r_refdef.view.height = r_fb.water.waterheight;
6156         r_refdef.view.useclipplane = true;
6157         myview = r_refdef.view;
6158         r_fb.water.renderingscene = true;
6159         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6160         {
6161                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6162                         continue;
6163                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6164                 {
6165                         r_refdef.view = myview;
6166                         if(r_water_scissormode.integer)
6167                         {
6168                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6169                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6170                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6171                         }
6172
6173                         // render reflected scene and copy into texture
6174                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6175                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6176                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6177                         r_refdef.view.clipplane = p->plane;
6178                         // reverse the cullface settings for this render
6179                         r_refdef.view.cullface_front = GL_FRONT;
6180                         r_refdef.view.cullface_back = GL_BACK;
6181                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6182                         {
6183                                 r_refdef.view.usecustompvs = true;
6184                                 if (p->pvsvalid)
6185                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6186                                 else
6187                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6188                         }
6189
6190                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6191                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6192                         R_ClearScreen(r_refdef.fogenabled);
6193                         if(r_water_scissormode.integer & 2)
6194                                 R_View_UpdateWithScissor(myscissor);
6195                         else
6196                                 R_View_Update();
6197                         R_AnimCache_CacheVisibleEntities();
6198                         if(r_water_scissormode.integer & 1)
6199                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6200                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6201
6202                         if (!p->fbo_reflection)
6203                                 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);
6204                         r_fb.water.hideplayer = false;
6205                 }
6206
6207                 // render the normal view scene and copy into texture
6208                 // (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)
6209                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6210                 {
6211                         r_refdef.view = myview;
6212                         if(r_water_scissormode.integer)
6213                         {
6214                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6215                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6216                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6217                         }
6218
6219                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6220
6221                         r_refdef.view.clipplane = p->plane;
6222                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6223                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6224
6225                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6226                         {
6227                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6228                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6229                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6230                                 R_RenderView_UpdateViewVectors();
6231                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6232                                 {
6233                                         r_refdef.view.usecustompvs = true;
6234                                         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);
6235                                 }
6236                         }
6237
6238                         PlaneClassify(&r_refdef.view.clipplane);
6239
6240                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6241                         R_ClearScreen(r_refdef.fogenabled);
6242                         if(r_water_scissormode.integer & 2)
6243                                 R_View_UpdateWithScissor(myscissor);
6244                         else
6245                                 R_View_Update();
6246                         R_AnimCache_CacheVisibleEntities();
6247                         if(r_water_scissormode.integer & 1)
6248                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6249                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6250
6251                         if (!p->fbo_refraction)
6252                                 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);
6253                         r_fb.water.hideplayer = false;
6254                 }
6255                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6256                 {
6257                         r_refdef.view = myview;
6258
6259                         r_refdef.view.clipplane = p->plane;
6260                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6261                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6262
6263                         r_refdef.view.width = r_fb.water.camerawidth;
6264                         r_refdef.view.height = r_fb.water.cameraheight;
6265                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6266                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6267                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6268                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6269
6270                         if(p->camera_entity)
6271                         {
6272                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6273                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6274                         }
6275
6276                         // note: all of the view is used for displaying... so
6277                         // there is no use in scissoring
6278
6279                         // reverse the cullface settings for this render
6280                         r_refdef.view.cullface_front = GL_FRONT;
6281                         r_refdef.view.cullface_back = GL_BACK;
6282                         // also reverse the view matrix
6283                         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
6284                         R_RenderView_UpdateViewVectors();
6285                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6286                         {
6287                                 r_refdef.view.usecustompvs = true;
6288                                 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);
6289                         }
6290                         
6291                         // camera needs no clipplane
6292                         r_refdef.view.useclipplane = false;
6293
6294                         PlaneClassify(&r_refdef.view.clipplane);
6295
6296                         r_fb.water.hideplayer = false;
6297
6298                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6299                         R_ClearScreen(r_refdef.fogenabled);
6300                         R_View_Update();
6301                         R_AnimCache_CacheVisibleEntities();
6302                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6303
6304                         if (!p->fbo_camera)
6305                                 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);
6306                         r_fb.water.hideplayer = false;
6307                 }
6308
6309         }
6310         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6311         r_fb.water.renderingscene = false;
6312         r_refdef.view = originalview;
6313         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6314         if (!r_fb.water.depthtexture)
6315                 R_ClearScreen(r_refdef.fogenabled);
6316         R_View_Update();
6317         R_AnimCache_CacheVisibleEntities();
6318         goto finish;
6319 error:
6320         r_refdef.view = originalview;
6321         r_fb.water.renderingscene = false;
6322         Cvar_SetValueQuick(&r_water, 0);
6323         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6324 finish:
6325         // lowquality hack, restore cvars
6326         if (qualityreduction > 0)
6327         {
6328                 if (qualityreduction >= 1)
6329                 {
6330                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6331                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6332                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6333                 }
6334                 if (qualityreduction >= 2)
6335                 {
6336                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6337                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6338                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6339                 }
6340         }
6341 }
6342
6343 static void R_Bloom_StartFrame(void)
6344 {
6345         int i;
6346         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6347         int viewwidth, viewheight;
6348         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6349         textype_t textype = TEXTYPE_COLORBUFFER;
6350
6351         switch (vid.renderpath)
6352         {
6353         case RENDERPATH_GL20:
6354                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6355                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6356                 {
6357                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6358                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6359                 }
6360                 break;
6361         case RENDERPATH_GL11:
6362         case RENDERPATH_GL13:
6363         case RENDERPATH_GLES1:
6364         case RENDERPATH_GLES2:
6365         case RENDERPATH_D3D9:
6366         case RENDERPATH_D3D10:
6367         case RENDERPATH_D3D11:
6368                 r_fb.usedepthtextures = false;
6369                 break;
6370         case RENDERPATH_SOFT:
6371                 r_fb.usedepthtextures = true;
6372                 break;
6373         }
6374
6375         if (r_viewscale_fpsscaling.integer)
6376         {
6377                 double actualframetime;
6378                 double targetframetime;
6379                 double adjust;
6380                 actualframetime = r_refdef.lastdrawscreentime;
6381                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6382                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6383                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6384                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6385                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6386                 viewscalefpsadjusted += adjust;
6387                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6388         }
6389         else
6390                 viewscalefpsadjusted = 1.0f;
6391
6392         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6393
6394         switch(vid.renderpath)
6395         {
6396         case RENDERPATH_GL20:
6397         case RENDERPATH_D3D9:
6398         case RENDERPATH_D3D10:
6399         case RENDERPATH_D3D11:
6400         case RENDERPATH_SOFT:
6401         case RENDERPATH_GLES2:
6402                 break;
6403         case RENDERPATH_GL11:
6404         case RENDERPATH_GL13:
6405         case RENDERPATH_GLES1:
6406                 return;
6407         }
6408
6409         // set bloomwidth and bloomheight to the bloom resolution that will be
6410         // used (often less than the screen resolution for faster rendering)
6411         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6412         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6413         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6414         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6415         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6416
6417         // calculate desired texture sizes
6418         if (vid.support.arb_texture_non_power_of_two)
6419         {
6420                 screentexturewidth = vid.width;
6421                 screentextureheight = vid.height;
6422                 bloomtexturewidth = r_fb.bloomwidth;
6423                 bloomtextureheight = r_fb.bloomheight;
6424         }
6425         else
6426         {
6427                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6428                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6429                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6430                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6431         }
6432
6433         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))
6434         {
6435                 Cvar_SetValueQuick(&r_bloom, 0);
6436                 Cvar_SetValueQuick(&r_motionblur, 0);
6437                 Cvar_SetValueQuick(&r_damageblur, 0);
6438         }
6439
6440         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6441          && !r_bloom.integer
6442          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6443          && !useviewfbo
6444          && r_viewscale.value == 1.0f
6445          && !r_viewscale_fpsscaling.integer)
6446                 screentexturewidth = screentextureheight = 0;
6447         if (!r_bloom.integer)
6448                 bloomtexturewidth = bloomtextureheight = 0;
6449
6450         // allocate textures as needed
6451         if (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          || useviewfbo != (r_fb.fbo != 0))
6457         {
6458                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6459                 {
6460                         if (r_fb.bloomtexture[i])
6461                                 R_FreeTexture(r_fb.bloomtexture[i]);
6462                         r_fb.bloomtexture[i] = NULL;
6463
6464                         if (r_fb.bloomfbo[i])
6465                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6466                         r_fb.bloomfbo[i] = 0;
6467                 }
6468
6469                 if (r_fb.fbo)
6470                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6471                 r_fb.fbo = 0;
6472
6473                 if (r_fb.colortexture)
6474                         R_FreeTexture(r_fb.colortexture);
6475                 r_fb.colortexture = NULL;
6476
6477                 if (r_fb.depthtexture)
6478                         R_FreeTexture(r_fb.depthtexture);
6479                 r_fb.depthtexture = NULL;
6480
6481                 if (r_fb.ghosttexture)
6482                         R_FreeTexture(r_fb.ghosttexture);
6483                 r_fb.ghosttexture = NULL;
6484
6485                 r_fb.screentexturewidth = screentexturewidth;
6486                 r_fb.screentextureheight = screentextureheight;
6487                 r_fb.bloomtexturewidth = bloomtexturewidth;
6488                 r_fb.bloomtextureheight = bloomtextureheight;
6489                 r_fb.textype = textype;
6490
6491                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6492                 {
6493                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6494                                 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);
6495                         r_fb.ghosttexture_valid = false;
6496                         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);
6497                         if (useviewfbo)
6498                         {
6499                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6500                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6501                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6502                         }
6503                 }
6504
6505                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6506                 {
6507                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6508                         {
6509                                 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);
6510                                 if (useviewfbo)
6511                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6512                         }
6513                 }
6514         }
6515
6516         // bloom texture is a different resolution
6517         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6518         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6519         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6520         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6521         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6522
6523         // set up a texcoord array for the full resolution screen image
6524         // (we have to keep this around to copy back during final render)
6525         r_fb.screentexcoord2f[0] = 0;
6526         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6527         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6528         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6529         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6530         r_fb.screentexcoord2f[5] = 0;
6531         r_fb.screentexcoord2f[6] = 0;
6532         r_fb.screentexcoord2f[7] = 0;
6533
6534         if(r_fb.fbo) 
6535         {
6536                 for (i = 1;i < 8;i += 2)
6537                 {
6538                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6539                 }
6540         }
6541
6542         // set up a texcoord array for the reduced resolution bloom image
6543         // (which will be additive blended over the screen image)
6544         r_fb.bloomtexcoord2f[0] = 0;
6545         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6546         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6547         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6548         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6549         r_fb.bloomtexcoord2f[5] = 0;
6550         r_fb.bloomtexcoord2f[6] = 0;
6551         r_fb.bloomtexcoord2f[7] = 0;
6552
6553         switch(vid.renderpath)
6554         {
6555         case RENDERPATH_GL11:
6556         case RENDERPATH_GL13:
6557         case RENDERPATH_GL20:
6558         case RENDERPATH_SOFT:
6559         case RENDERPATH_GLES1:
6560         case RENDERPATH_GLES2:
6561                 break;
6562         case RENDERPATH_D3D9:
6563         case RENDERPATH_D3D10:
6564         case RENDERPATH_D3D11:
6565                 for (i = 0;i < 4;i++)
6566                 {
6567                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6568                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6569                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6570                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6571                 }
6572                 break;
6573         }
6574
6575         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6576
6577         if (r_fb.fbo)
6578                 r_refdef.view.clear = true;
6579 }
6580
6581 static void R_Bloom_MakeTexture(void)
6582 {
6583         int x, range, dir;
6584         float xoffset, yoffset, r, brighten;
6585         rtexture_t *intex;
6586         float colorscale = r_bloom_colorscale.value;
6587
6588         r_refdef.stats[r_stat_bloom]++;
6589     
6590 #if 0
6591     // this copy is unnecessary since it happens in R_BlendView already
6592         if (!r_fb.fbo)
6593         {
6594                 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);
6595                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6596         }
6597 #endif
6598
6599         // scale down screen texture to the bloom texture size
6600         CHECKGLERROR
6601         r_fb.bloomindex = 0;
6602         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6603         R_SetViewport(&r_fb.bloomviewport);
6604         GL_DepthTest(false);
6605         GL_BlendFunc(GL_ONE, GL_ZERO);
6606         GL_Color(colorscale, colorscale, colorscale, 1);
6607         // 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...
6608         switch(vid.renderpath)
6609         {
6610         case RENDERPATH_GL11:
6611         case RENDERPATH_GL13:
6612         case RENDERPATH_GL20:
6613         case RENDERPATH_GLES1:
6614         case RENDERPATH_GLES2:
6615         case RENDERPATH_SOFT:
6616                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6617                 break;
6618         case RENDERPATH_D3D9:
6619         case RENDERPATH_D3D10:
6620         case RENDERPATH_D3D11:
6621                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6622                 break;
6623         }
6624         // TODO: do boxfilter scale-down in shader?
6625         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6626         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6627         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6628
6629         // we now have a properly scaled bloom image
6630         if (!r_fb.bloomfbo[r_fb.bloomindex])
6631         {
6632                 // copy it into the bloom texture
6633                 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);
6634                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6635         }
6636
6637         // multiply bloom image by itself as many times as desired
6638         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6639         {
6640                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6641                 r_fb.bloomindex ^= 1;
6642                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6643                 x *= 2;
6644                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6645                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6646                 {
6647                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6648                         GL_Color(r,r,r,1); // apply fix factor
6649                 }
6650                 else
6651                 {
6652                         if(x <= 2)
6653                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6654                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6655                         GL_Color(1,1,1,1); // no fix factor supported here
6656                 }
6657                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6658                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6659                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6660                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6661
6662                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6663                 {
6664                         // copy the darkened image to a texture
6665                         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);
6666                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6667                 }
6668         }
6669
6670         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6671         brighten = r_bloom_brighten.value;
6672         brighten = sqrt(brighten);
6673         if(range >= 1)
6674                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6675
6676         for (dir = 0;dir < 2;dir++)
6677         {
6678                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6679                 r_fb.bloomindex ^= 1;
6680                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6681                 // blend on at multiple vertical offsets to achieve a vertical blur
6682                 // TODO: do offset blends using GLSL
6683                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6684                 GL_BlendFunc(GL_ONE, GL_ZERO);
6685                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6686                 for (x = -range;x <= range;x++)
6687                 {
6688                         if (!dir){xoffset = 0;yoffset = x;}
6689                         else {xoffset = x;yoffset = 0;}
6690                         xoffset /= (float)r_fb.bloomtexturewidth;
6691                         yoffset /= (float)r_fb.bloomtextureheight;
6692                         // compute a texcoord array with the specified x and y offset
6693                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6694                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6695                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6696                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6697                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6698                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6699                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6700                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6701                         // this r value looks like a 'dot' particle, fading sharply to
6702                         // black at the edges
6703                         // (probably not realistic but looks good enough)
6704                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6705                         //r = brighten/(range*2+1);
6706                         r = brighten / (range * 2 + 1);
6707                         if(range >= 1)
6708                                 r *= (1 - x*x/(float)(range*range));
6709                         GL_Color(r, r, r, 1);
6710                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6711                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6712                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6713                         GL_BlendFunc(GL_ONE, GL_ONE);
6714                 }
6715
6716                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6717                 {
6718                         // copy the vertically or horizontally blurred bloom view to a texture
6719                         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);
6720                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6721                 }
6722         }
6723 }
6724
6725 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6726 {
6727         unsigned int permutation;
6728         float uservecs[4][4];
6729
6730         R_EntityMatrix(&identitymatrix);
6731
6732         switch (vid.renderpath)
6733         {
6734         case RENDERPATH_GL20:
6735         case RENDERPATH_D3D9:
6736         case RENDERPATH_D3D10:
6737         case RENDERPATH_D3D11:
6738         case RENDERPATH_SOFT:
6739         case RENDERPATH_GLES2:
6740                 permutation =
6741                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6742                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6743                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6744                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6745                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6746
6747                 if (r_fb.colortexture)
6748                 {
6749                         if (!r_fb.fbo)
6750                         {
6751                                 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);
6752                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6753                         }
6754
6755                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6756                         {
6757                                 // declare variables
6758                                 float blur_factor, blur_mouseaccel, blur_velocity;
6759                                 static float blur_average; 
6760                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6761
6762                                 // set a goal for the factoring
6763                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6764                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6765                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6766                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6767                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6768                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6769
6770                                 // from the goal, pick an averaged value between goal and last value
6771                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6772                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6773
6774                                 // enforce minimum amount of blur 
6775                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6776
6777                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6778
6779                                 // calculate values into a standard alpha
6780                                 cl.motionbluralpha = 1 - exp(-
6781                                                 (
6782                                                  (r_motionblur.value * blur_factor / 80)
6783                                                  +
6784                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6785                                                 )
6786                                                 /
6787                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6788                                           );
6789
6790                                 // randomization for the blur value to combat persistent ghosting
6791                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6792                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6793
6794                                 // apply the blur
6795                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6796                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6797                                 {
6798                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6799                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6800                                         switch(vid.renderpath)
6801                                         {
6802                                         case RENDERPATH_GL11:
6803                                         case RENDERPATH_GL13:
6804                                         case RENDERPATH_GL20:
6805                                         case RENDERPATH_GLES1:
6806                                         case RENDERPATH_GLES2:
6807                                         case RENDERPATH_SOFT:
6808                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6809                                                 break;
6810                                         case RENDERPATH_D3D9:
6811                                         case RENDERPATH_D3D10:
6812                                         case RENDERPATH_D3D11:
6813                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6814                                                 break;
6815                                         }
6816                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6817                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6818                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6819                                 }
6820
6821                                 // updates old view angles for next pass
6822                                 VectorCopy(cl.viewangles, blur_oldangles);
6823
6824                                 // copy view into the ghost texture
6825                                 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);
6826                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6827                                 r_fb.ghosttexture_valid = true;
6828                         }
6829                 }
6830                 else
6831                 {
6832                         // no r_fb.colortexture means we're rendering to the real fb
6833                         // we may still have to do view tint...
6834                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6835                         {
6836                                 // apply a color tint to the whole view
6837                                 R_ResetViewRendering2D(0, NULL, NULL);
6838                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6839                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6840                                 R_SetupShader_Generic_NoTexture(false, true);
6841                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6842                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6843                         }
6844                         break; // no screen processing, no bloom, skip it
6845                 }
6846
6847                 if (r_fb.bloomtexture[0])
6848                 {
6849                         // make the bloom texture
6850                         R_Bloom_MakeTexture();
6851                 }
6852
6853 #if _MSC_VER >= 1400
6854 #define sscanf sscanf_s
6855 #endif
6856                 memset(uservecs, 0, sizeof(uservecs));
6857                 if (r_glsl_postprocess_uservec1_enable.integer)
6858                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6859                 if (r_glsl_postprocess_uservec2_enable.integer)
6860                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6861                 if (r_glsl_postprocess_uservec3_enable.integer)
6862                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6863                 if (r_glsl_postprocess_uservec4_enable.integer)
6864                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6865
6866                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6867                 GL_Color(1, 1, 1, 1);
6868                 GL_BlendFunc(GL_ONE, GL_ZERO);
6869
6870                 switch(vid.renderpath)
6871                 {
6872                 case RENDERPATH_GL20:
6873                 case RENDERPATH_GLES2:
6874                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6875                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6876                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6877                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6878                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6879                         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]);
6880                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6881                         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]);
6882                         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]);
6883                         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]);
6884                         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]);
6885                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6886                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6887                         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);
6888                         break;
6889                 case RENDERPATH_D3D9:
6890 #ifdef SUPPORTD3D
6891                         // 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...
6892                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6893                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6894                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6895                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6896                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6897                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6898                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6899                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6900                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6901                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6902                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6903                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6904                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6905                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6906 #endif
6907                         break;
6908                 case RENDERPATH_D3D10:
6909                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6910                         break;
6911                 case RENDERPATH_D3D11:
6912                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6913                         break;
6914                 case RENDERPATH_SOFT:
6915                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6916                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6917                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6918                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6919                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6920                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6921                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6922                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6923                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6924                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6925                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6926                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6927                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6928                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6929                         break;
6930                 default:
6931                         break;
6932                 }
6933                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6934                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6935                 break;
6936         case RENDERPATH_GL11:
6937         case RENDERPATH_GL13:
6938         case RENDERPATH_GLES1:
6939                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6940                 {
6941                         // apply a color tint to the whole view
6942                         R_ResetViewRendering2D(0, NULL, NULL);
6943                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6944                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6945                         R_SetupShader_Generic_NoTexture(false, true);
6946                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6947                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6948                 }
6949                 break;
6950         }
6951 }
6952
6953 matrix4x4_t r_waterscrollmatrix;
6954
6955 void R_UpdateFog(void)
6956 {
6957         // Nehahra fog
6958         if (gamemode == GAME_NEHAHRA)
6959         {
6960                 if (gl_fogenable.integer)
6961                 {
6962                         r_refdef.oldgl_fogenable = true;
6963                         r_refdef.fog_density = gl_fogdensity.value;
6964                         r_refdef.fog_red = gl_fogred.value;
6965                         r_refdef.fog_green = gl_foggreen.value;
6966                         r_refdef.fog_blue = gl_fogblue.value;
6967                         r_refdef.fog_alpha = 1;
6968                         r_refdef.fog_start = 0;
6969                         r_refdef.fog_end = gl_skyclip.value;
6970                         r_refdef.fog_height = 1<<30;
6971                         r_refdef.fog_fadedepth = 128;
6972                 }
6973                 else if (r_refdef.oldgl_fogenable)
6974                 {
6975                         r_refdef.oldgl_fogenable = false;
6976                         r_refdef.fog_density = 0;
6977                         r_refdef.fog_red = 0;
6978                         r_refdef.fog_green = 0;
6979                         r_refdef.fog_blue = 0;
6980                         r_refdef.fog_alpha = 0;
6981                         r_refdef.fog_start = 0;
6982                         r_refdef.fog_end = 0;
6983                         r_refdef.fog_height = 1<<30;
6984                         r_refdef.fog_fadedepth = 128;
6985                 }
6986         }
6987
6988         // fog parms
6989         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6990         r_refdef.fog_start = max(0, r_refdef.fog_start);
6991         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6992
6993         if (r_refdef.fog_density && r_drawfog.integer)
6994         {
6995                 r_refdef.fogenabled = true;
6996                 // this is the point where the fog reaches 0.9986 alpha, which we
6997                 // consider a good enough cutoff point for the texture
6998                 // (0.9986 * 256 == 255.6)
6999                 if (r_fog_exp2.integer)
7000                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7001                 else
7002                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7003                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7004                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7005                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7006                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7007                         R_BuildFogHeightTexture();
7008                 // fog color was already set
7009                 // update the fog texture
7010                 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)
7011                         R_BuildFogTexture();
7012                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7013                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7014         }
7015         else
7016                 r_refdef.fogenabled = false;
7017
7018         // fog color
7019         if (r_refdef.fog_density)
7020         {
7021                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7022                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7023                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7024
7025                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7026                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7027                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7028                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7029
7030                 {
7031                         vec3_t fogvec;
7032                         VectorCopy(r_refdef.fogcolor, fogvec);
7033                         //   color.rgb *= ContrastBoost * SceneBrightness;
7034                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7035                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7036                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7037                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7038                 }
7039         }
7040 }
7041
7042 void R_UpdateVariables(void)
7043 {
7044         R_Textures_Frame();
7045
7046         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7047
7048         r_refdef.farclip = r_farclip_base.value;
7049         if (r_refdef.scene.worldmodel)
7050                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7051         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7052
7053         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7054                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7055         r_refdef.polygonfactor = 0;
7056         r_refdef.polygonoffset = 0;
7057         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7058         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7059
7060         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7061         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7062         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7063         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7064         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7065         if (FAKELIGHT_ENABLED)
7066         {
7067                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7068         }
7069         else if (r_refdef.scene.worldmodel)
7070         {
7071                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7072         }
7073         if (r_showsurfaces.integer)
7074         {
7075                 r_refdef.scene.rtworld = false;
7076                 r_refdef.scene.rtworldshadows = false;
7077                 r_refdef.scene.rtdlight = false;
7078                 r_refdef.scene.rtdlightshadows = false;
7079                 r_refdef.lightmapintensity = 0;
7080         }
7081
7082         r_gpuskeletal = false;
7083         switch(vid.renderpath)
7084         {
7085         case RENDERPATH_GL20:
7086                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7087         case RENDERPATH_D3D9:
7088         case RENDERPATH_D3D10:
7089         case RENDERPATH_D3D11:
7090         case RENDERPATH_SOFT:
7091         case RENDERPATH_GLES2:
7092                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7093                 {
7094                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7095                         {
7096                                 // build GLSL gamma texture
7097 #define RAMPWIDTH 256
7098                                 unsigned short ramp[RAMPWIDTH * 3];
7099                                 unsigned char rampbgr[RAMPWIDTH][4];
7100                                 int i;
7101
7102                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7103
7104                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7105                                 for(i = 0; i < RAMPWIDTH; ++i)
7106                                 {
7107                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7108                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7109                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7110                                         rampbgr[i][3] = 0;
7111                                 }
7112                                 if (r_texture_gammaramps)
7113                                 {
7114                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7115                                 }
7116                                 else
7117                                 {
7118                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7119                                 }
7120                         }
7121                 }
7122                 else
7123                 {
7124                         // remove GLSL gamma texture
7125                 }
7126                 break;
7127         case RENDERPATH_GL11:
7128         case RENDERPATH_GL13:
7129         case RENDERPATH_GLES1:
7130                 break;
7131         }
7132 }
7133
7134 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7135 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7136 /*
7137 ================
7138 R_SelectScene
7139 ================
7140 */
7141 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7142         if( scenetype != r_currentscenetype ) {
7143                 // store the old scenetype
7144                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7145                 r_currentscenetype = scenetype;
7146                 // move in the new scene
7147                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7148         }
7149 }
7150
7151 /*
7152 ================
7153 R_GetScenePointer
7154 ================
7155 */
7156 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7157 {
7158         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7159         if( scenetype == r_currentscenetype ) {
7160                 return &r_refdef.scene;
7161         } else {
7162                 return &r_scenes_store[ scenetype ];
7163         }
7164 }
7165
7166 static int R_SortEntities_Compare(const void *ap, const void *bp)
7167 {
7168         const entity_render_t *a = *(const entity_render_t **)ap;
7169         const entity_render_t *b = *(const entity_render_t **)bp;
7170
7171         // 1. compare model
7172         if(a->model < b->model)
7173                 return -1;
7174         if(a->model > b->model)
7175                 return +1;
7176
7177         // 2. compare skin
7178         // TODO possibly calculate the REAL skinnum here first using
7179         // skinscenes?
7180         if(a->skinnum < b->skinnum)
7181                 return -1;
7182         if(a->skinnum > b->skinnum)
7183                 return +1;
7184
7185         // everything we compared is equal
7186         return 0;
7187 }
7188 static void R_SortEntities(void)
7189 {
7190         // below or equal 2 ents, sorting never gains anything
7191         if(r_refdef.scene.numentities <= 2)
7192                 return;
7193         // sort
7194         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7195 }
7196
7197 /*
7198 ================
7199 R_RenderView
7200 ================
7201 */
7202 int dpsoftrast_test;
7203 extern cvar_t r_shadow_bouncegrid;
7204 void R_RenderView(void)
7205 {
7206         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7207         int fbo;
7208         rtexture_t *depthtexture;
7209         rtexture_t *colortexture;
7210
7211         dpsoftrast_test = r_test.integer;
7212
7213         if (r_timereport_active)
7214                 R_TimeReport("start");
7215         r_textureframe++; // used only by R_GetCurrentTexture
7216         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7217
7218         if(R_CompileShader_CheckStaticParms())
7219                 R_GLSL_Restart_f();
7220
7221         if (!r_drawentities.integer)
7222                 r_refdef.scene.numentities = 0;
7223         else if (r_sortentities.integer)
7224                 R_SortEntities();
7225
7226         R_AnimCache_ClearCache();
7227
7228         /* adjust for stereo display */
7229         if(R_Stereo_Active())
7230         {
7231                 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);
7232                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7233         }
7234
7235         if (r_refdef.view.isoverlay)
7236         {
7237                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7238                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7239                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7240                 R_TimeReport("depthclear");
7241
7242                 r_refdef.view.showdebug = false;
7243
7244                 r_fb.water.enabled = false;
7245                 r_fb.water.numwaterplanes = 0;
7246
7247                 R_RenderScene(0, NULL, NULL);
7248
7249                 r_refdef.view.matrix = originalmatrix;
7250
7251                 CHECKGLERROR
7252                 return;
7253         }
7254
7255         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7256         {
7257                 r_refdef.view.matrix = originalmatrix;
7258                 return;
7259         }
7260
7261         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7262
7263         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7264                 // in sRGB fallback, behave similar to true sRGB: convert this
7265                 // value from linear to sRGB
7266                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7267
7268         R_RenderView_UpdateViewVectors();
7269
7270         R_Shadow_UpdateWorldLightSelection();
7271
7272         R_Bloom_StartFrame();
7273
7274         // apply bloom brightness offset
7275         if(r_fb.bloomtexture[0])
7276                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7277
7278         R_Water_StartFrame();
7279
7280         // now we probably have an fbo to render into
7281         fbo = r_fb.fbo;
7282         depthtexture = r_fb.depthtexture;
7283         colortexture = r_fb.colortexture;
7284
7285         CHECKGLERROR
7286         if (r_timereport_active)
7287                 R_TimeReport("viewsetup");
7288
7289         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7290
7291         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7292         {
7293                 R_ClearScreen(r_refdef.fogenabled);
7294                 if (r_timereport_active)
7295                         R_TimeReport("viewclear");
7296         }
7297         r_refdef.view.clear = true;
7298
7299         r_refdef.view.showdebug = true;
7300
7301         R_View_Update();
7302         if (r_timereport_active)
7303                 R_TimeReport("visibility");
7304
7305         R_AnimCache_CacheVisibleEntities();
7306         if (r_timereport_active)
7307                 R_TimeReport("animcache");
7308
7309         R_Shadow_UpdateBounceGridTexture();
7310         if (r_timereport_active && r_shadow_bouncegrid.integer)
7311                 R_TimeReport("bouncegrid");
7312
7313         r_fb.water.numwaterplanes = 0;
7314         if (r_fb.water.enabled)
7315                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7316
7317         R_RenderScene(fbo, depthtexture, colortexture);
7318         r_fb.water.numwaterplanes = 0;
7319
7320         R_BlendView(fbo, depthtexture, colortexture);
7321         if (r_timereport_active)
7322                 R_TimeReport("blendview");
7323
7324         GL_Scissor(0, 0, vid.width, vid.height);
7325         GL_ScissorTest(false);
7326
7327         r_refdef.view.matrix = originalmatrix;
7328
7329         CHECKGLERROR
7330 }
7331
7332 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7333 {
7334         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7335         {
7336                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7337                 if (r_timereport_active)
7338                         R_TimeReport("waterworld");
7339         }
7340
7341         // don't let sound skip if going slow
7342         if (r_refdef.scene.extraupdate)
7343                 S_ExtraUpdate ();
7344
7345         R_DrawModelsAddWaterPlanes();
7346         if (r_timereport_active)
7347                 R_TimeReport("watermodels");
7348
7349         if (r_fb.water.numwaterplanes)
7350         {
7351                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7352                 if (r_timereport_active)
7353                         R_TimeReport("waterscenes");
7354         }
7355 }
7356
7357 extern cvar_t cl_locs_show;
7358 static void R_DrawLocs(void);
7359 static void R_DrawEntityBBoxes(void);
7360 static void R_DrawModelDecals(void);
7361 extern cvar_t cl_decals_newsystem;
7362 extern qboolean r_shadow_usingdeferredprepass;
7363 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7364 {
7365         qboolean shadowmapping = false;
7366
7367         if (r_timereport_active)
7368                 R_TimeReport("beginscene");
7369
7370         r_refdef.stats[r_stat_renders]++;
7371
7372         R_UpdateFog();
7373
7374         // don't let sound skip if going slow
7375         if (r_refdef.scene.extraupdate)
7376                 S_ExtraUpdate ();
7377
7378         R_MeshQueue_BeginScene();
7379
7380         R_SkyStartFrame();
7381
7382         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);
7383
7384         if (r_timereport_active)
7385                 R_TimeReport("skystartframe");
7386
7387         if (cl.csqc_vidvars.drawworld)
7388         {
7389                 // don't let sound skip if going slow
7390                 if (r_refdef.scene.extraupdate)
7391                         S_ExtraUpdate ();
7392
7393                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7394                 {
7395                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7396                         if (r_timereport_active)
7397                                 R_TimeReport("worldsky");
7398                 }
7399
7400                 if (R_DrawBrushModelsSky() && r_timereport_active)
7401                         R_TimeReport("bmodelsky");
7402
7403                 if (skyrendermasked && skyrenderlater)
7404                 {
7405                         // we have to force off the water clipping plane while rendering sky
7406                         R_SetupView(false, fbo, depthtexture, colortexture);
7407                         R_Sky();
7408                         R_SetupView(true, fbo, depthtexture, colortexture);
7409                         if (r_timereport_active)
7410                                 R_TimeReport("sky");
7411                 }
7412         }
7413
7414         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7415         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7416                 R_Shadow_PrepareModelShadows();
7417         if (r_timereport_active)
7418                 R_TimeReport("preparelights");
7419
7420         if (R_Shadow_ShadowMappingEnabled())
7421                 shadowmapping = true;
7422
7423         if (r_shadow_usingdeferredprepass)
7424                 R_Shadow_DrawPrepass();
7425
7426         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7427         {
7428                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7429                 if (r_timereport_active)
7430                         R_TimeReport("worlddepth");
7431         }
7432         if (r_depthfirst.integer >= 2)
7433         {
7434                 R_DrawModelsDepth();
7435                 if (r_timereport_active)
7436                         R_TimeReport("modeldepth");
7437         }
7438
7439         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7440         {
7441                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7442                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7443                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7444                 // don't let sound skip if going slow
7445                 if (r_refdef.scene.extraupdate)
7446                         S_ExtraUpdate ();
7447         }
7448
7449         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7450         {
7451                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7452                 if (r_timereport_active)
7453                         R_TimeReport("world");
7454         }
7455
7456         // don't let sound skip if going slow
7457         if (r_refdef.scene.extraupdate)
7458                 S_ExtraUpdate ();
7459
7460         R_DrawModels();
7461         if (r_timereport_active)
7462                 R_TimeReport("models");
7463
7464         // don't let sound skip if going slow
7465         if (r_refdef.scene.extraupdate)
7466                 S_ExtraUpdate ();
7467
7468         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7469         {
7470                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7471                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7472                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7473                 // don't let sound skip if going slow
7474                 if (r_refdef.scene.extraupdate)
7475                         S_ExtraUpdate ();
7476         }
7477
7478         if (!r_shadow_usingdeferredprepass)
7479         {
7480                 R_Shadow_DrawLights();
7481                 if (r_timereport_active)
7482                         R_TimeReport("rtlights");
7483         }
7484
7485         // don't let sound skip if going slow
7486         if (r_refdef.scene.extraupdate)
7487                 S_ExtraUpdate ();
7488
7489         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7490         {
7491                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7492                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7493                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7494                 // don't let sound skip if going slow
7495                 if (r_refdef.scene.extraupdate)
7496                         S_ExtraUpdate ();
7497         }
7498
7499         if (cl.csqc_vidvars.drawworld)
7500         {
7501                 if (cl_decals_newsystem.integer)
7502                 {
7503                         R_DrawModelDecals();
7504                         if (r_timereport_active)
7505                                 R_TimeReport("modeldecals");
7506                 }
7507                 else
7508                 {
7509                         R_DrawDecals();
7510                         if (r_timereport_active)
7511                                 R_TimeReport("decals");
7512                 }
7513
7514                 R_DrawParticles();
7515                 if (r_timereport_active)
7516                         R_TimeReport("particles");
7517
7518                 R_DrawExplosions();
7519                 if (r_timereport_active)
7520                         R_TimeReport("explosions");
7521
7522                 R_DrawLightningBeams();
7523                 if (r_timereport_active)
7524                         R_TimeReport("lightning");
7525         }
7526
7527         if (cl.csqc_loaded)
7528                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7529
7530         if (r_refdef.view.showdebug)
7531         {
7532                 if (cl_locs_show.integer)
7533                 {
7534                         R_DrawLocs();
7535                         if (r_timereport_active)
7536                                 R_TimeReport("showlocs");
7537                 }
7538
7539                 if (r_drawportals.integer)
7540                 {
7541                         R_DrawPortals();
7542                         if (r_timereport_active)
7543                                 R_TimeReport("portals");
7544                 }
7545
7546                 if (r_showbboxes.value > 0)
7547                 {
7548                         R_DrawEntityBBoxes();
7549                         if (r_timereport_active)
7550                                 R_TimeReport("bboxes");
7551                 }
7552         }
7553
7554         if (r_transparent.integer)
7555         {
7556                 R_MeshQueue_RenderTransparent();
7557                 if (r_timereport_active)
7558                         R_TimeReport("drawtrans");
7559         }
7560
7561         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))
7562         {
7563                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7564                 if (r_timereport_active)
7565                         R_TimeReport("worlddebug");
7566                 R_DrawModelsDebug();
7567                 if (r_timereport_active)
7568                         R_TimeReport("modeldebug");
7569         }
7570
7571         if (cl.csqc_vidvars.drawworld)
7572         {
7573                 R_Shadow_DrawCoronas();
7574                 if (r_timereport_active)
7575                         R_TimeReport("coronas");
7576         }
7577
7578 #if 0
7579         {
7580                 GL_DepthTest(false);
7581                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7582                 GL_Color(1, 1, 1, 1);
7583                 qglBegin(GL_POLYGON);
7584                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7585                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7586                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7587                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7588                 qglEnd();
7589                 qglBegin(GL_POLYGON);
7590                 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]);
7591                 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]);
7592                 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]);
7593                 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]);
7594                 qglEnd();
7595                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7596         }
7597 #endif
7598
7599         // don't let sound skip if going slow
7600         if (r_refdef.scene.extraupdate)
7601                 S_ExtraUpdate ();
7602 }
7603
7604 static const unsigned short bboxelements[36] =
7605 {
7606         5, 1, 3, 5, 3, 7,
7607         6, 2, 0, 6, 0, 4,
7608         7, 3, 2, 7, 2, 6,
7609         4, 0, 1, 4, 1, 5,
7610         4, 5, 7, 4, 7, 6,
7611         1, 0, 2, 1, 2, 3,
7612 };
7613
7614 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7615 {
7616         int i;
7617         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7618
7619         RSurf_ActiveWorldEntity();
7620
7621         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7622         GL_DepthMask(false);
7623         GL_DepthRange(0, 1);
7624         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7625 //      R_Mesh_ResetTextureState();
7626
7627         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7628         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7629         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7630         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7631         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7632         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7633         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7634         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7635         R_FillColors(color4f, 8, cr, cg, cb, ca);
7636         if (r_refdef.fogenabled)
7637         {
7638                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7639                 {
7640                         f1 = RSurf_FogVertex(v);
7641                         f2 = 1 - f1;
7642                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7643                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7644                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7645                 }
7646         }
7647         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7648         R_Mesh_ResetTextureState();
7649         R_SetupShader_Generic_NoTexture(false, false);
7650         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7651 }
7652
7653 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7654 {
7655         prvm_prog_t *prog = SVVM_prog;
7656         int i;
7657         float color[4];
7658         prvm_edict_t *edict;
7659
7660         // this function draws bounding boxes of server entities
7661         if (!sv.active)
7662                 return;
7663
7664         GL_CullFace(GL_NONE);
7665         R_SetupShader_Generic_NoTexture(false, false);
7666
7667         for (i = 0;i < numsurfaces;i++)
7668         {
7669                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7670                 switch ((int)PRVM_serveredictfloat(edict, solid))
7671                 {
7672                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7673                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7674                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7675                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7676                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7677                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7678                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7679                 }
7680                 color[3] *= r_showbboxes.value;
7681                 color[3] = bound(0, color[3], 1);
7682                 GL_DepthTest(!r_showdisabledepthtest.integer);
7683                 GL_CullFace(r_refdef.view.cullface_front);
7684                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7685         }
7686 }
7687
7688 static void R_DrawEntityBBoxes(void)
7689 {
7690         int i;
7691         prvm_edict_t *edict;
7692         vec3_t center;
7693         prvm_prog_t *prog = SVVM_prog;
7694
7695         // this function draws bounding boxes of server entities
7696         if (!sv.active)
7697                 return;
7698
7699         for (i = 0;i < prog->num_edicts;i++)
7700         {
7701                 edict = PRVM_EDICT_NUM(i);
7702                 if (edict->priv.server->free)
7703                         continue;
7704                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7705                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7706                         continue;
7707                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7708                         continue;
7709                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7710                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7711         }
7712 }
7713
7714 static const int nomodelelement3i[24] =
7715 {
7716         5, 2, 0,
7717         5, 1, 2,
7718         5, 0, 3,
7719         5, 3, 1,
7720         0, 2, 4,
7721         2, 1, 4,
7722         3, 0, 4,
7723         1, 3, 4
7724 };
7725
7726 static const unsigned short nomodelelement3s[24] =
7727 {
7728         5, 2, 0,
7729         5, 1, 2,
7730         5, 0, 3,
7731         5, 3, 1,
7732         0, 2, 4,
7733         2, 1, 4,
7734         3, 0, 4,
7735         1, 3, 4
7736 };
7737
7738 static const float nomodelvertex3f[6*3] =
7739 {
7740         -16,   0,   0,
7741          16,   0,   0,
7742           0, -16,   0,
7743           0,  16,   0,
7744           0,   0, -16,
7745           0,   0,  16
7746 };
7747
7748 static const float nomodelcolor4f[6*4] =
7749 {
7750         0.0f, 0.0f, 0.5f, 1.0f,
7751         0.0f, 0.0f, 0.5f, 1.0f,
7752         0.0f, 0.5f, 0.0f, 1.0f,
7753         0.0f, 0.5f, 0.0f, 1.0f,
7754         0.5f, 0.0f, 0.0f, 1.0f,
7755         0.5f, 0.0f, 0.0f, 1.0f
7756 };
7757
7758 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7759 {
7760         int i;
7761         float f1, f2, *c;
7762         float color4f[6*4];
7763
7764         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);
7765
7766         // this is only called once per entity so numsurfaces is always 1, and
7767         // surfacelist is always {0}, so this code does not handle batches
7768
7769         if (rsurface.ent_flags & RENDER_ADDITIVE)
7770         {
7771                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7772                 GL_DepthMask(false);
7773         }
7774         else if (rsurface.colormod[3] < 1)
7775         {
7776                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7777                 GL_DepthMask(false);
7778         }
7779         else
7780         {
7781                 GL_BlendFunc(GL_ONE, GL_ZERO);
7782                 GL_DepthMask(true);
7783         }
7784         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7785         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7786         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7787         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7788         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7789         for (i = 0, c = color4f;i < 6;i++, c += 4)
7790         {
7791                 c[0] *= rsurface.colormod[0];
7792                 c[1] *= rsurface.colormod[1];
7793                 c[2] *= rsurface.colormod[2];
7794                 c[3] *= rsurface.colormod[3];
7795         }
7796         if (r_refdef.fogenabled)
7797         {
7798                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7799                 {
7800                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7801                         f2 = 1 - f1;
7802                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7803                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7804                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7805                 }
7806         }
7807 //      R_Mesh_ResetTextureState();
7808         R_SetupShader_Generic_NoTexture(false, false);
7809         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7810         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7811 }
7812
7813 void R_DrawNoModel(entity_render_t *ent)
7814 {
7815         vec3_t org;
7816         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7817         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7818                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7819         else
7820                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7821 }
7822
7823 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7824 {
7825         vec3_t right1, right2, diff, normal;
7826
7827         VectorSubtract (org2, org1, normal);
7828
7829         // calculate 'right' vector for start
7830         VectorSubtract (r_refdef.view.origin, org1, diff);
7831         CrossProduct (normal, diff, right1);
7832         VectorNormalize (right1);
7833
7834         // calculate 'right' vector for end
7835         VectorSubtract (r_refdef.view.origin, org2, diff);
7836         CrossProduct (normal, diff, right2);
7837         VectorNormalize (right2);
7838
7839         vert[ 0] = org1[0] + width * right1[0];
7840         vert[ 1] = org1[1] + width * right1[1];
7841         vert[ 2] = org1[2] + width * right1[2];
7842         vert[ 3] = org1[0] - width * right1[0];
7843         vert[ 4] = org1[1] - width * right1[1];
7844         vert[ 5] = org1[2] - width * right1[2];
7845         vert[ 6] = org2[0] - width * right2[0];
7846         vert[ 7] = org2[1] - width * right2[1];
7847         vert[ 8] = org2[2] - width * right2[2];
7848         vert[ 9] = org2[0] + width * right2[0];
7849         vert[10] = org2[1] + width * right2[1];
7850         vert[11] = org2[2] + width * right2[2];
7851 }
7852
7853 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)
7854 {
7855         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7856         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7857         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7858         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7859         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7860         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7861         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7862         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7863         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7864         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7865         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7866         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7867 }
7868
7869 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7870 {
7871         int i;
7872         float *vertex3f;
7873         float v[3];
7874         VectorSet(v, x, y, z);
7875         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7876                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7877                         break;
7878         if (i == mesh->numvertices)
7879         {
7880                 if (mesh->numvertices < mesh->maxvertices)
7881                 {
7882                         VectorCopy(v, vertex3f);
7883                         mesh->numvertices++;
7884                 }
7885                 return mesh->numvertices;
7886         }
7887         else
7888                 return i;
7889 }
7890
7891 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7892 {
7893         int i;
7894         int *e, element[3];
7895         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7896         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7897         e = mesh->element3i + mesh->numtriangles * 3;
7898         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7899         {
7900                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7901                 if (mesh->numtriangles < mesh->maxtriangles)
7902                 {
7903                         *e++ = element[0];
7904                         *e++ = element[1];
7905                         *e++ = element[2];
7906                         mesh->numtriangles++;
7907                 }
7908                 element[1] = element[2];
7909         }
7910 }
7911
7912 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7913 {
7914         int i;
7915         int *e, element[3];
7916         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7917         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7918         e = mesh->element3i + mesh->numtriangles * 3;
7919         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7920         {
7921                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7922                 if (mesh->numtriangles < mesh->maxtriangles)
7923                 {
7924                         *e++ = element[0];
7925                         *e++ = element[1];
7926                         *e++ = element[2];
7927                         mesh->numtriangles++;
7928                 }
7929                 element[1] = element[2];
7930         }
7931 }
7932
7933 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7934 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7935 {
7936         int planenum, planenum2;
7937         int w;
7938         int tempnumpoints;
7939         mplane_t *plane, *plane2;
7940         double maxdist;
7941         double temppoints[2][256*3];
7942         // figure out how large a bounding box we need to properly compute this brush
7943         maxdist = 0;
7944         for (w = 0;w < numplanes;w++)
7945                 maxdist = max(maxdist, fabs(planes[w].dist));
7946         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7947         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7948         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7949         {
7950                 w = 0;
7951                 tempnumpoints = 4;
7952                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7953                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7954                 {
7955                         if (planenum2 == planenum)
7956                                 continue;
7957                         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);
7958                         w = !w;
7959                 }
7960                 if (tempnumpoints < 3)
7961                         continue;
7962                 // generate elements forming a triangle fan for this polygon
7963                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7964         }
7965 }
7966
7967 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)
7968 {
7969         texturelayer_t *layer;
7970         layer = t->currentlayers + t->currentnumlayers++;
7971         layer->type = type;
7972         layer->depthmask = depthmask;
7973         layer->blendfunc1 = blendfunc1;
7974         layer->blendfunc2 = blendfunc2;
7975         layer->texture = texture;
7976         layer->texmatrix = *matrix;
7977         layer->color[0] = r;
7978         layer->color[1] = g;
7979         layer->color[2] = b;
7980         layer->color[3] = a;
7981 }
7982
7983 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7984 {
7985         if(parms[0] == 0 && parms[1] == 0)
7986                 return false;
7987         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7988                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7989                         return false;
7990         return true;
7991 }
7992
7993 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7994 {
7995         double index, f;
7996         index = parms[2] + rsurface.shadertime * parms[3];
7997         index -= floor(index);
7998         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7999         {
8000         default:
8001         case Q3WAVEFUNC_NONE:
8002         case Q3WAVEFUNC_NOISE:
8003         case Q3WAVEFUNC_COUNT:
8004                 f = 0;
8005                 break;
8006         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8007         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8008         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8009         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8010         case Q3WAVEFUNC_TRIANGLE:
8011                 index *= 4;
8012                 f = index - floor(index);
8013                 if (index < 1)
8014                 {
8015                         // f = f;
8016                 }
8017                 else if (index < 2)
8018                         f = 1 - f;
8019                 else if (index < 3)
8020                         f = -f;
8021                 else
8022                         f = -(1 - f);
8023                 break;
8024         }
8025         f = parms[0] + parms[1] * f;
8026         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8027                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8028         return (float) f;
8029 }
8030
8031 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8032 {
8033         int w, h, idx;
8034         float shadertime;
8035         float f;
8036         float offsetd[2];
8037         float tcmat[12];
8038         matrix4x4_t matrix, temp;
8039         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8040         // it's better to have one huge fixup every 9 hours than gradual
8041         // degradation over time which looks consistently bad after many hours.
8042         //
8043         // tcmod scroll in particular suffers from this degradation which can't be
8044         // effectively worked around even with floor() tricks because we don't
8045         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8046         // a workaround involving floor() would be incorrect anyway...
8047         shadertime = rsurface.shadertime;
8048         if (shadertime >= 32768.0f)
8049                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8050         switch(tcmod->tcmod)
8051         {
8052                 case Q3TCMOD_COUNT:
8053                 case Q3TCMOD_NONE:
8054                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8055                                 matrix = r_waterscrollmatrix;
8056                         else
8057                                 matrix = identitymatrix;
8058                         break;
8059                 case Q3TCMOD_ENTITYTRANSLATE:
8060                         // this is used in Q3 to allow the gamecode to control texcoord
8061                         // scrolling on the entity, which is not supported in darkplaces yet.
8062                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8063                         break;
8064                 case Q3TCMOD_ROTATE:
8065                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8066                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8067                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8068                         break;
8069                 case Q3TCMOD_SCALE:
8070                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8071                         break;
8072                 case Q3TCMOD_SCROLL:
8073                         // this particular tcmod is a "bug for bug" compatible one with regards to
8074                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8075                         // specifically did the wrapping and so we must mimic that...
8076                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8077                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8078                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8079                         break;
8080                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8081                         w = (int) tcmod->parms[0];
8082                         h = (int) tcmod->parms[1];
8083                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8084                         f = f - floor(f);
8085                         idx = (int) floor(f * w * h);
8086                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8087                         break;
8088                 case Q3TCMOD_STRETCH:
8089                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8090                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8091                         break;
8092                 case Q3TCMOD_TRANSFORM:
8093                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8094                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8095                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8096                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8097                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8098                         break;
8099                 case Q3TCMOD_TURBULENT:
8100                         // this is handled in the RSurf_PrepareVertices function
8101                         matrix = identitymatrix;
8102                         break;
8103         }
8104         temp = *texmatrix;
8105         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8106 }
8107
8108 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8109 {
8110         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8111         char name[MAX_QPATH];
8112         skinframe_t *skinframe;
8113         unsigned char pixels[296*194];
8114         strlcpy(cache->name, skinname, sizeof(cache->name));
8115         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8116         if (developer_loading.integer)
8117                 Con_Printf("loading %s\n", name);
8118         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8119         if (!skinframe || !skinframe->base)
8120         {
8121                 unsigned char *f;
8122                 fs_offset_t filesize;
8123                 skinframe = NULL;
8124                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8125                 if (f)
8126                 {
8127                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8128                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8129                         Mem_Free(f);
8130                 }
8131         }
8132         cache->skinframe = skinframe;
8133 }
8134
8135 texture_t *R_GetCurrentTexture(texture_t *t)
8136 {
8137         int i;
8138         const entity_render_t *ent = rsurface.entity;
8139         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8140         q3shaderinfo_layer_tcmod_t *tcmod;
8141
8142         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8143                 return t->currentframe;
8144         t->update_lastrenderframe = r_textureframe;
8145         t->update_lastrenderentity = (void *)ent;
8146
8147         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8148                 t->camera_entity = ent->entitynumber;
8149         else
8150                 t->camera_entity = 0;
8151
8152         // switch to an alternate material if this is a q1bsp animated material
8153         {
8154                 texture_t *texture = t;
8155                 int s = rsurface.ent_skinnum;
8156                 if ((unsigned int)s >= (unsigned int)model->numskins)
8157                         s = 0;
8158                 if (model->skinscenes)
8159                 {
8160                         if (model->skinscenes[s].framecount > 1)
8161                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8162                         else
8163                                 s = model->skinscenes[s].firstframe;
8164                 }
8165                 if (s > 0)
8166                         t = t + s * model->num_surfaces;
8167                 if (t->animated)
8168                 {
8169                         // use an alternate animation if the entity's frame is not 0,
8170                         // and only if the texture has an alternate animation
8171                         if (t->animated == 2) // q2bsp
8172                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8173                         else if (rsurface.ent_alttextures && t->anim_total[1])
8174                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8175                         else
8176                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8177                 }
8178                 texture->currentframe = t;
8179         }
8180
8181         // update currentskinframe to be a qw skin or animation frame
8182         if (rsurface.ent_qwskin >= 0)
8183         {
8184                 i = rsurface.ent_qwskin;
8185                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8186                 {
8187                         r_qwskincache_size = cl.maxclients;
8188                         if (r_qwskincache)
8189                                 Mem_Free(r_qwskincache);
8190                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8191                 }
8192                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8193                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8194                 t->currentskinframe = r_qwskincache[i].skinframe;
8195                 if (t->currentskinframe == NULL)
8196                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8197         }
8198         else if (t->numskinframes >= 2)
8199                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8200         if (t->backgroundnumskinframes >= 2)
8201                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8202
8203         t->currentmaterialflags = t->basematerialflags;
8204         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8205         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8206                 t->currentalpha *= r_wateralpha.value;
8207         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8208                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8209         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8210                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8211         if (!(rsurface.ent_flags & RENDER_LIGHT))
8212                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8213         else if (FAKELIGHT_ENABLED)
8214         {
8215                 // no modellight if using fakelight for the map
8216         }
8217         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8218         {
8219                 // pick a model lighting mode
8220                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8221                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8222                 else
8223                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8224         }
8225         if (rsurface.ent_flags & RENDER_ADDITIVE)
8226                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8227         else if (t->currentalpha < 1)
8228                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8229         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8230         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8231                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8232         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8233                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8234         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8235                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8236         if (t->backgroundnumskinframes)
8237                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8238         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8239         {
8240                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8241                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8242         }
8243         else
8244                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8245         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8246         {
8247                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8248                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8249         }
8250         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8251                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8252
8253         // there is no tcmod
8254         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8255         {
8256                 t->currenttexmatrix = r_waterscrollmatrix;
8257                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8258         }
8259         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8260         {
8261                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8262                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8263         }
8264
8265         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8266                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8267         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8268                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8269
8270         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8271         if (t->currentskinframe->qpixels)
8272                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8273         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8274         if (!t->basetexture)
8275                 t->basetexture = r_texture_notexture;
8276         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8277         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8278         t->nmaptexture = t->currentskinframe->nmap;
8279         if (!t->nmaptexture)
8280                 t->nmaptexture = r_texture_blanknormalmap;
8281         t->glosstexture = r_texture_black;
8282         t->glowtexture = t->currentskinframe->glow;
8283         t->fogtexture = t->currentskinframe->fog;
8284         t->reflectmasktexture = t->currentskinframe->reflect;
8285         if (t->backgroundnumskinframes)
8286         {
8287                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8288                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8289                 t->backgroundglosstexture = r_texture_black;
8290                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8291                 if (!t->backgroundnmaptexture)
8292                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8293                 // make sure that if glow is going to be used, both textures are not NULL
8294                 if (!t->backgroundglowtexture && t->glowtexture)
8295                         t->backgroundglowtexture = r_texture_black;
8296                 if (!t->glowtexture && t->backgroundglowtexture)
8297                         t->glowtexture = r_texture_black;
8298         }
8299         else
8300         {
8301                 t->backgroundbasetexture = r_texture_white;
8302                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8303                 t->backgroundglosstexture = r_texture_black;
8304                 t->backgroundglowtexture = NULL;
8305         }
8306         t->specularpower = r_shadow_glossexponent.value;
8307         // TODO: store reference values for these in the texture?
8308         t->specularscale = 0;
8309         if (r_shadow_gloss.integer > 0)
8310         {
8311                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8312                 {
8313                         if (r_shadow_glossintensity.value > 0)
8314                         {
8315                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8316                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8317                                 t->specularscale = r_shadow_glossintensity.value;
8318                         }
8319                 }
8320                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8321                 {
8322                         t->glosstexture = r_texture_white;
8323                         t->backgroundglosstexture = r_texture_white;
8324                         t->specularscale = r_shadow_gloss2intensity.value;
8325                         t->specularpower = r_shadow_gloss2exponent.value;
8326                 }
8327         }
8328         t->specularscale *= t->specularscalemod;
8329         t->specularpower *= t->specularpowermod;
8330         t->rtlightambient = 0;
8331
8332         // lightmaps mode looks bad with dlights using actual texturing, so turn
8333         // off the colormap and glossmap, but leave the normalmap on as it still
8334         // accurately represents the shading involved
8335         if (gl_lightmaps.integer)
8336         {
8337                 t->basetexture = r_texture_grey128;
8338                 t->pantstexture = r_texture_black;
8339                 t->shirttexture = r_texture_black;
8340                 if (gl_lightmaps.integer < 2)
8341                         t->nmaptexture = r_texture_blanknormalmap;
8342                 t->glosstexture = r_texture_black;
8343                 t->glowtexture = NULL;
8344                 t->fogtexture = NULL;
8345                 t->reflectmasktexture = NULL;
8346                 t->backgroundbasetexture = NULL;
8347                 if (gl_lightmaps.integer < 2)
8348                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8349                 t->backgroundglosstexture = r_texture_black;
8350                 t->backgroundglowtexture = NULL;
8351                 t->specularscale = 0;
8352                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8353         }
8354
8355         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8356         VectorClear(t->dlightcolor);
8357         t->currentnumlayers = 0;
8358         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8359         {
8360                 int blendfunc1, blendfunc2;
8361                 qboolean depthmask;
8362                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8363                 {
8364                         blendfunc1 = GL_SRC_ALPHA;
8365                         blendfunc2 = GL_ONE;
8366                 }
8367                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8368                 {
8369                         blendfunc1 = GL_SRC_ALPHA;
8370                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8371                 }
8372                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8373                 {
8374                         blendfunc1 = t->customblendfunc[0];
8375                         blendfunc2 = t->customblendfunc[1];
8376                 }
8377                 else
8378                 {
8379                         blendfunc1 = GL_ONE;
8380                         blendfunc2 = GL_ZERO;
8381                 }
8382                 // don't colormod evilblend textures
8383                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8384                         VectorSet(t->lightmapcolor, 1, 1, 1);
8385                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8386                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8387                 {
8388                         // fullbright is not affected by r_refdef.lightmapintensity
8389                         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]);
8390                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8391                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8392                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8393                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_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]);
8394                 }
8395                 else
8396                 {
8397                         vec3_t ambientcolor;
8398                         float colorscale;
8399                         // set the color tint used for lights affecting this surface
8400                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8401                         colorscale = 2;
8402                         // q3bsp has no lightmap updates, so the lightstylevalue that
8403                         // would normally be baked into the lightmap must be
8404                         // applied to the color
8405                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8406                         if (model->type == mod_brushq3)
8407                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8408                         colorscale *= r_refdef.lightmapintensity;
8409                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8410                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8411                         // basic lit geometry
8412                         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]);
8413                         // add pants/shirt if needed
8414                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8415                                 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]);
8416                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8417                                 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]);
8418                         // now add ambient passes if needed
8419                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8420                         {
8421                                 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]);
8422                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8423                                         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]);
8424                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8425                                         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]);
8426                         }
8427                 }
8428                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8429                         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]);
8430                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8431                 {
8432                         // if this is opaque use alpha blend which will darken the earlier
8433                         // passes cheaply.
8434                         //
8435                         // if this is an alpha blended material, all the earlier passes
8436                         // were darkened by fog already, so we only need to add the fog
8437                         // color ontop through the fog mask texture
8438                         //
8439                         // if this is an additive blended material, all the earlier passes
8440                         // were darkened by fog already, and we should not add fog color
8441                         // (because the background was not darkened, there is no fog color
8442                         // that was lost behind it).
8443                         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]);
8444                 }
8445         }
8446
8447         return t;
8448 }
8449
8450 rsurfacestate_t rsurface;
8451
8452 void RSurf_ActiveWorldEntity(void)
8453 {
8454         dp_model_t *model = r_refdef.scene.worldmodel;
8455         //if (rsurface.entity == r_refdef.scene.worldentity)
8456         //      return;
8457         rsurface.entity = r_refdef.scene.worldentity;
8458         rsurface.skeleton = NULL;
8459         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8460         rsurface.ent_skinnum = 0;
8461         rsurface.ent_qwskin = -1;
8462         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8463         rsurface.shadertime = r_refdef.scene.time;
8464         rsurface.matrix = identitymatrix;
8465         rsurface.inversematrix = identitymatrix;
8466         rsurface.matrixscale = 1;
8467         rsurface.inversematrixscale = 1;
8468         R_EntityMatrix(&identitymatrix);
8469         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8470         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8471         rsurface.fograngerecip = r_refdef.fograngerecip;
8472         rsurface.fogheightfade = r_refdef.fogheightfade;
8473         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8474         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8475         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8476         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8477         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8478         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8479         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8480         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8481         rsurface.colormod[3] = 1;
8482         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);
8483         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8484         rsurface.frameblend[0].lerp = 1;
8485         rsurface.ent_alttextures = false;
8486         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8487         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8488         rsurface.entityskeletaltransform3x4 = NULL;
8489         rsurface.entityskeletaltransform3x4buffer = NULL;
8490         rsurface.entityskeletaltransform3x4offset = 0;
8491         rsurface.entityskeletaltransform3x4size = 0;;
8492         rsurface.entityskeletalnumtransforms = 0;
8493         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8494         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8495         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8496         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8497         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8498         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8499         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8500         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8501         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8502         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8503         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8504         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8505         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8506         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8507         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8508         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8509         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8510         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8511         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8512         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8513         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8514         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8515         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8516         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8517         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8518         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8519         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8520         rsurface.modelelement3i = model->surfmesh.data_element3i;
8521         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8522         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8523         rsurface.modelelement3s = model->surfmesh.data_element3s;
8524         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8525         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8526         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8527         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8528         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8529         rsurface.modelsurfaces = model->data_surfaces;
8530         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8531         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8532         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8533         rsurface.modelgeneratedvertex = false;
8534         rsurface.batchgeneratedvertex = false;
8535         rsurface.batchfirstvertex = 0;
8536         rsurface.batchnumvertices = 0;
8537         rsurface.batchfirsttriangle = 0;
8538         rsurface.batchnumtriangles = 0;
8539         rsurface.batchvertex3f  = NULL;
8540         rsurface.batchvertex3f_vertexbuffer = NULL;
8541         rsurface.batchvertex3f_bufferoffset = 0;
8542         rsurface.batchsvector3f = NULL;
8543         rsurface.batchsvector3f_vertexbuffer = NULL;
8544         rsurface.batchsvector3f_bufferoffset = 0;
8545         rsurface.batchtvector3f = NULL;
8546         rsurface.batchtvector3f_vertexbuffer = NULL;
8547         rsurface.batchtvector3f_bufferoffset = 0;
8548         rsurface.batchnormal3f  = NULL;
8549         rsurface.batchnormal3f_vertexbuffer = NULL;
8550         rsurface.batchnormal3f_bufferoffset = 0;
8551         rsurface.batchlightmapcolor4f = NULL;
8552         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8553         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8554         rsurface.batchtexcoordtexture2f = NULL;
8555         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8556         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8557         rsurface.batchtexcoordlightmap2f = NULL;
8558         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8559         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8560         rsurface.batchskeletalindex4ub = NULL;
8561         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8562         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8563         rsurface.batchskeletalweight4ub = NULL;
8564         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8565         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8566         rsurface.batchvertexmesh = NULL;
8567         rsurface.batchvertexmesh_vertexbuffer = NULL;
8568         rsurface.batchvertexmesh_bufferoffset = 0;
8569         rsurface.batchelement3i = NULL;
8570         rsurface.batchelement3i_indexbuffer = NULL;
8571         rsurface.batchelement3i_bufferoffset = 0;
8572         rsurface.batchelement3s = NULL;
8573         rsurface.batchelement3s_indexbuffer = NULL;
8574         rsurface.batchelement3s_bufferoffset = 0;
8575         rsurface.passcolor4f = NULL;
8576         rsurface.passcolor4f_vertexbuffer = NULL;
8577         rsurface.passcolor4f_bufferoffset = 0;
8578         rsurface.forcecurrenttextureupdate = false;
8579 }
8580
8581 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8582 {
8583         dp_model_t *model = ent->model;
8584         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8585         //      return;
8586         rsurface.entity = (entity_render_t *)ent;
8587         rsurface.skeleton = ent->skeleton;
8588         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8589         rsurface.ent_skinnum = ent->skinnum;
8590         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;
8591         rsurface.ent_flags = ent->flags;
8592         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8593         rsurface.matrix = ent->matrix;
8594         rsurface.inversematrix = ent->inversematrix;
8595         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8596         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8597         R_EntityMatrix(&rsurface.matrix);
8598         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8599         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8600         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8601         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8602         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8603         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8604         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8605         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8606         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8607         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8608         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8609         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8610         rsurface.colormod[3] = ent->alpha;
8611         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8612         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8613         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8614         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8615         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8616         if (ent->model->brush.submodel && !prepass)
8617         {
8618                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8619                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8620         }
8621         // if the animcache code decided it should use the shader path, skip the deform step
8622         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8623         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8624         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8625         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8626         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8627         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8628         {
8629                 if (ent->animcache_vertex3f)
8630                 {
8631                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8632                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8633                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8634                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8635                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8636                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8637                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8638                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8639                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8640                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8641                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8642                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8643                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8644                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8645                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8646                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8647                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8648                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8649                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8650                 }
8651                 else if (wanttangents)
8652                 {
8653                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8654                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8655                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8656                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8657                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8658                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8659                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8660                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8661                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8662                         rsurface.modelvertexmesh = NULL;
8663                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8664                         rsurface.modelvertexmesh_bufferoffset = 0;
8665                         rsurface.modelvertex3f_vertexbuffer = NULL;
8666                         rsurface.modelvertex3f_bufferoffset = 0;
8667                         rsurface.modelvertex3f_vertexbuffer = 0;
8668                         rsurface.modelvertex3f_bufferoffset = 0;
8669                         rsurface.modelsvector3f_vertexbuffer = 0;
8670                         rsurface.modelsvector3f_bufferoffset = 0;
8671                         rsurface.modeltvector3f_vertexbuffer = 0;
8672                         rsurface.modeltvector3f_bufferoffset = 0;
8673                         rsurface.modelnormal3f_vertexbuffer = 0;
8674                         rsurface.modelnormal3f_bufferoffset = 0;
8675                 }
8676                 else if (wantnormals)
8677                 {
8678                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8679                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8680                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8681                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8682                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8683                         rsurface.modelsvector3f = NULL;
8684                         rsurface.modeltvector3f = NULL;
8685                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8686                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8687                         rsurface.modelvertexmesh = NULL;
8688                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8689                         rsurface.modelvertexmesh_bufferoffset = 0;
8690                         rsurface.modelvertex3f_vertexbuffer = NULL;
8691                         rsurface.modelvertex3f_bufferoffset = 0;
8692                         rsurface.modelvertex3f_vertexbuffer = 0;
8693                         rsurface.modelvertex3f_bufferoffset = 0;
8694                         rsurface.modelsvector3f_vertexbuffer = 0;
8695                         rsurface.modelsvector3f_bufferoffset = 0;
8696                         rsurface.modeltvector3f_vertexbuffer = 0;
8697                         rsurface.modeltvector3f_bufferoffset = 0;
8698                         rsurface.modelnormal3f_vertexbuffer = 0;
8699                         rsurface.modelnormal3f_bufferoffset = 0;
8700                 }
8701                 else
8702                 {
8703                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8704                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8705                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8706                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8707                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8708                         rsurface.modelsvector3f = NULL;
8709                         rsurface.modeltvector3f = NULL;
8710                         rsurface.modelnormal3f = NULL;
8711                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8712                         rsurface.modelvertexmesh = NULL;
8713                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8714                         rsurface.modelvertexmesh_bufferoffset = 0;
8715                         rsurface.modelvertex3f_vertexbuffer = NULL;
8716                         rsurface.modelvertex3f_bufferoffset = 0;
8717                         rsurface.modelvertex3f_vertexbuffer = 0;
8718                         rsurface.modelvertex3f_bufferoffset = 0;
8719                         rsurface.modelsvector3f_vertexbuffer = 0;
8720                         rsurface.modelsvector3f_bufferoffset = 0;
8721                         rsurface.modeltvector3f_vertexbuffer = 0;
8722                         rsurface.modeltvector3f_bufferoffset = 0;
8723                         rsurface.modelnormal3f_vertexbuffer = 0;
8724                         rsurface.modelnormal3f_bufferoffset = 0;
8725                 }
8726                 rsurface.modelgeneratedvertex = true;
8727         }
8728         else
8729         {
8730                 if (rsurface.entityskeletaltransform3x4)
8731                 {
8732                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8733                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8734                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8735                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8736                 }
8737                 else
8738                 {
8739                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8740                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8741                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8742                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8743                 }
8744                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8745                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8746                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8747                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8748                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8749                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8750                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8751                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8752                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8753                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8754                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8755                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8756                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8757                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8758                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8759                 rsurface.modelgeneratedvertex = false;
8760         }
8761         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8762         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8763         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8764         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8765         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8766         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8767         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8768         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8769         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8770         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8771         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8772         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8773         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8774         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8775         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8776         rsurface.modelelement3i = model->surfmesh.data_element3i;
8777         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8778         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8779         rsurface.modelelement3s = model->surfmesh.data_element3s;
8780         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8781         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8782         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8783         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8784         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8785         rsurface.modelsurfaces = model->data_surfaces;
8786         rsurface.batchgeneratedvertex = false;
8787         rsurface.batchfirstvertex = 0;
8788         rsurface.batchnumvertices = 0;
8789         rsurface.batchfirsttriangle = 0;
8790         rsurface.batchnumtriangles = 0;
8791         rsurface.batchvertex3f  = NULL;
8792         rsurface.batchvertex3f_vertexbuffer = NULL;
8793         rsurface.batchvertex3f_bufferoffset = 0;
8794         rsurface.batchsvector3f = NULL;
8795         rsurface.batchsvector3f_vertexbuffer = NULL;
8796         rsurface.batchsvector3f_bufferoffset = 0;
8797         rsurface.batchtvector3f = NULL;
8798         rsurface.batchtvector3f_vertexbuffer = NULL;
8799         rsurface.batchtvector3f_bufferoffset = 0;
8800         rsurface.batchnormal3f  = NULL;
8801         rsurface.batchnormal3f_vertexbuffer = NULL;
8802         rsurface.batchnormal3f_bufferoffset = 0;
8803         rsurface.batchlightmapcolor4f = NULL;
8804         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8805         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8806         rsurface.batchtexcoordtexture2f = NULL;
8807         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8808         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8809         rsurface.batchtexcoordlightmap2f = NULL;
8810         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8811         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8812         rsurface.batchskeletalindex4ub = NULL;
8813         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8814         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8815         rsurface.batchskeletalweight4ub = NULL;
8816         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8817         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8818         rsurface.batchvertexmesh = NULL;
8819         rsurface.batchvertexmesh_vertexbuffer = NULL;
8820         rsurface.batchvertexmesh_bufferoffset = 0;
8821         rsurface.batchelement3i = NULL;
8822         rsurface.batchelement3i_indexbuffer = NULL;
8823         rsurface.batchelement3i_bufferoffset = 0;
8824         rsurface.batchelement3s = NULL;
8825         rsurface.batchelement3s_indexbuffer = NULL;
8826         rsurface.batchelement3s_bufferoffset = 0;
8827         rsurface.passcolor4f = NULL;
8828         rsurface.passcolor4f_vertexbuffer = NULL;
8829         rsurface.passcolor4f_bufferoffset = 0;
8830         rsurface.forcecurrenttextureupdate = false;
8831 }
8832
8833 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)
8834 {
8835         rsurface.entity = r_refdef.scene.worldentity;
8836         rsurface.skeleton = NULL;
8837         rsurface.ent_skinnum = 0;
8838         rsurface.ent_qwskin = -1;
8839         rsurface.ent_flags = entflags;
8840         rsurface.shadertime = r_refdef.scene.time - shadertime;
8841         rsurface.modelnumvertices = numvertices;
8842         rsurface.modelnumtriangles = numtriangles;
8843         rsurface.matrix = *matrix;
8844         rsurface.inversematrix = *inversematrix;
8845         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8846         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8847         R_EntityMatrix(&rsurface.matrix);
8848         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8849         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8850         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8851         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8852         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8853         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8854         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8855         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8856         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8857         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8858         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8859         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8860         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);
8861         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8862         rsurface.frameblend[0].lerp = 1;
8863         rsurface.ent_alttextures = false;
8864         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8865         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8866         rsurface.entityskeletaltransform3x4 = NULL;
8867         rsurface.entityskeletaltransform3x4buffer = NULL;
8868         rsurface.entityskeletaltransform3x4offset = 0;
8869         rsurface.entityskeletaltransform3x4size = 0;
8870         rsurface.entityskeletalnumtransforms = 0;
8871         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8872         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8873         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8874         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8875         if (wanttangents)
8876         {
8877                 rsurface.modelvertex3f = (float *)vertex3f;
8878                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8879                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8880                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8881         }
8882         else if (wantnormals)
8883         {
8884                 rsurface.modelvertex3f = (float *)vertex3f;
8885                 rsurface.modelsvector3f = NULL;
8886                 rsurface.modeltvector3f = NULL;
8887                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8888         }
8889         else
8890         {
8891                 rsurface.modelvertex3f = (float *)vertex3f;
8892                 rsurface.modelsvector3f = NULL;
8893                 rsurface.modeltvector3f = NULL;
8894                 rsurface.modelnormal3f = NULL;
8895         }
8896         rsurface.modelvertexmesh = NULL;
8897         rsurface.modelvertexmesh_vertexbuffer = NULL;
8898         rsurface.modelvertexmesh_bufferoffset = 0;
8899         rsurface.modelvertex3f_vertexbuffer = 0;
8900         rsurface.modelvertex3f_bufferoffset = 0;
8901         rsurface.modelsvector3f_vertexbuffer = 0;
8902         rsurface.modelsvector3f_bufferoffset = 0;
8903         rsurface.modeltvector3f_vertexbuffer = 0;
8904         rsurface.modeltvector3f_bufferoffset = 0;
8905         rsurface.modelnormal3f_vertexbuffer = 0;
8906         rsurface.modelnormal3f_bufferoffset = 0;
8907         rsurface.modelgeneratedvertex = true;
8908         rsurface.modellightmapcolor4f  = (float *)color4f;
8909         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8910         rsurface.modellightmapcolor4f_bufferoffset = 0;
8911         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8912         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8913         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8914         rsurface.modeltexcoordlightmap2f  = NULL;
8915         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8916         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8917         rsurface.modelskeletalindex4ub = NULL;
8918         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8919         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8920         rsurface.modelskeletalweight4ub = NULL;
8921         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8922         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8923         rsurface.modelelement3i = (int *)element3i;
8924         rsurface.modelelement3i_indexbuffer = NULL;
8925         rsurface.modelelement3i_bufferoffset = 0;
8926         rsurface.modelelement3s = (unsigned short *)element3s;
8927         rsurface.modelelement3s_indexbuffer = NULL;
8928         rsurface.modelelement3s_bufferoffset = 0;
8929         rsurface.modellightmapoffsets = NULL;
8930         rsurface.modelsurfaces = NULL;
8931         rsurface.batchgeneratedvertex = false;
8932         rsurface.batchfirstvertex = 0;
8933         rsurface.batchnumvertices = 0;
8934         rsurface.batchfirsttriangle = 0;
8935         rsurface.batchnumtriangles = 0;
8936         rsurface.batchvertex3f  = NULL;
8937         rsurface.batchvertex3f_vertexbuffer = NULL;
8938         rsurface.batchvertex3f_bufferoffset = 0;
8939         rsurface.batchsvector3f = NULL;
8940         rsurface.batchsvector3f_vertexbuffer = NULL;
8941         rsurface.batchsvector3f_bufferoffset = 0;
8942         rsurface.batchtvector3f = NULL;
8943         rsurface.batchtvector3f_vertexbuffer = NULL;
8944         rsurface.batchtvector3f_bufferoffset = 0;
8945         rsurface.batchnormal3f  = NULL;
8946         rsurface.batchnormal3f_vertexbuffer = NULL;
8947         rsurface.batchnormal3f_bufferoffset = 0;
8948         rsurface.batchlightmapcolor4f = NULL;
8949         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8950         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8951         rsurface.batchtexcoordtexture2f = NULL;
8952         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8953         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8954         rsurface.batchtexcoordlightmap2f = NULL;
8955         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8956         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8957         rsurface.batchskeletalindex4ub = NULL;
8958         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8959         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8960         rsurface.batchskeletalweight4ub = NULL;
8961         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8962         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8963         rsurface.batchvertexmesh = NULL;
8964         rsurface.batchvertexmesh_vertexbuffer = NULL;
8965         rsurface.batchvertexmesh_bufferoffset = 0;
8966         rsurface.batchelement3i = NULL;
8967         rsurface.batchelement3i_indexbuffer = NULL;
8968         rsurface.batchelement3i_bufferoffset = 0;
8969         rsurface.batchelement3s = NULL;
8970         rsurface.batchelement3s_indexbuffer = NULL;
8971         rsurface.batchelement3s_bufferoffset = 0;
8972         rsurface.passcolor4f = NULL;
8973         rsurface.passcolor4f_vertexbuffer = NULL;
8974         rsurface.passcolor4f_bufferoffset = 0;
8975         rsurface.forcecurrenttextureupdate = true;
8976
8977         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8978         {
8979                 if ((wantnormals || wanttangents) && !normal3f)
8980                 {
8981                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8982                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8983                 }
8984                 if (wanttangents && !svector3f)
8985                 {
8986                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8987                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8988                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8989                 }
8990         }
8991 }
8992
8993 float RSurf_FogPoint(const float *v)
8994 {
8995         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8996         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8997         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8998         float FogHeightFade = r_refdef.fogheightfade;
8999         float fogfrac;
9000         unsigned int fogmasktableindex;
9001         if (r_refdef.fogplaneviewabove)
9002                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9003         else
9004                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9005         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9006         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9007 }
9008
9009 float RSurf_FogVertex(const float *v)
9010 {
9011         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9012         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9013         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9014         float FogHeightFade = rsurface.fogheightfade;
9015         float fogfrac;
9016         unsigned int fogmasktableindex;
9017         if (r_refdef.fogplaneviewabove)
9018                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9019         else
9020                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9021         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9022         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9023 }
9024
9025 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9026 {
9027         int i;
9028         for (i = 0;i < numelements;i++)
9029                 outelement3i[i] = inelement3i[i] + adjust;
9030 }
9031
9032 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9033 extern cvar_t gl_vbo;
9034 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9035 {
9036         int deformindex;
9037         int firsttriangle;
9038         int numtriangles;
9039         int firstvertex;
9040         int endvertex;
9041         int numvertices;
9042         int surfacefirsttriangle;
9043         int surfacenumtriangles;
9044         int surfacefirstvertex;
9045         int surfaceendvertex;
9046         int surfacenumvertices;
9047         int batchnumsurfaces = texturenumsurfaces;
9048         int batchnumvertices;
9049         int batchnumtriangles;
9050         int needsupdate;
9051         int i, j;
9052         qboolean gaps;
9053         qboolean dynamicvertex;
9054         float amplitude;
9055         float animpos;
9056         float scale;
9057         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9058         float waveparms[4];
9059         unsigned char *ub;
9060         q3shaderinfo_deform_t *deform;
9061         const msurface_t *surface, *firstsurface;
9062         r_vertexmesh_t *vertexmesh;
9063         if (!texturenumsurfaces)
9064                 return;
9065         // find vertex range of this surface batch
9066         gaps = false;
9067         firstsurface = texturesurfacelist[0];
9068         firsttriangle = firstsurface->num_firsttriangle;
9069         batchnumvertices = 0;
9070         batchnumtriangles = 0;
9071         firstvertex = endvertex = firstsurface->num_firstvertex;
9072         for (i = 0;i < texturenumsurfaces;i++)
9073         {
9074                 surface = texturesurfacelist[i];
9075                 if (surface != firstsurface + i)
9076                         gaps = true;
9077                 surfacefirstvertex = surface->num_firstvertex;
9078                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9079                 surfacenumvertices = surface->num_vertices;
9080                 surfacenumtriangles = surface->num_triangles;
9081                 if (firstvertex > surfacefirstvertex)
9082                         firstvertex = surfacefirstvertex;
9083                 if (endvertex < surfaceendvertex)
9084                         endvertex = surfaceendvertex;
9085                 batchnumvertices += surfacenumvertices;
9086                 batchnumtriangles += surfacenumtriangles;
9087         }
9088
9089         r_refdef.stats[r_stat_batch_batches]++;
9090         if (gaps)
9091                 r_refdef.stats[r_stat_batch_withgaps]++;
9092         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9093         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9094         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9095
9096         // we now know the vertex range used, and if there are any gaps in it
9097         rsurface.batchfirstvertex = firstvertex;
9098         rsurface.batchnumvertices = endvertex - firstvertex;
9099         rsurface.batchfirsttriangle = firsttriangle;
9100         rsurface.batchnumtriangles = batchnumtriangles;
9101
9102         // this variable holds flags for which properties have been updated that
9103         // may require regenerating vertexmesh array...
9104         needsupdate = 0;
9105
9106         // check if any dynamic vertex processing must occur
9107         dynamicvertex = false;
9108
9109         // a cvar to force the dynamic vertex path to be taken, for debugging
9110         if (r_batch_debugdynamicvertexpath.integer)
9111         {
9112                 if (!dynamicvertex)
9113                 {
9114                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9115                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9116                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9117                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9118                 }
9119                 dynamicvertex = true;
9120         }
9121
9122         // if there is a chance of animated vertex colors, it's a dynamic batch
9123         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9124         {
9125                 if (!dynamicvertex)
9126                 {
9127                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9128                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9129                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9130                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9131                 }
9132                 dynamicvertex = true;
9133                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9134         }
9135
9136         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9137         {
9138                 switch (deform->deform)
9139                 {
9140                 default:
9141                 case Q3DEFORM_PROJECTIONSHADOW:
9142                 case Q3DEFORM_TEXT0:
9143                 case Q3DEFORM_TEXT1:
9144                 case Q3DEFORM_TEXT2:
9145                 case Q3DEFORM_TEXT3:
9146                 case Q3DEFORM_TEXT4:
9147                 case Q3DEFORM_TEXT5:
9148                 case Q3DEFORM_TEXT6:
9149                 case Q3DEFORM_TEXT7:
9150                 case Q3DEFORM_NONE:
9151                         break;
9152                 case Q3DEFORM_AUTOSPRITE:
9153                         if (!dynamicvertex)
9154                         {
9155                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9156                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9157                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9158                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9159                         }
9160                         dynamicvertex = true;
9161                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9162                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9163                         break;
9164                 case Q3DEFORM_AUTOSPRITE2:
9165                         if (!dynamicvertex)
9166                         {
9167                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9168                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9169                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9170                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9171                         }
9172                         dynamicvertex = true;
9173                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9174                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9175                         break;
9176                 case Q3DEFORM_NORMAL:
9177                         if (!dynamicvertex)
9178                         {
9179                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9180                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9181                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9182                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9183                         }
9184                         dynamicvertex = true;
9185                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9186                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9187                         break;
9188                 case Q3DEFORM_WAVE:
9189                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9190                                 break; // if wavefunc is a nop, ignore this transform
9191                         if (!dynamicvertex)
9192                         {
9193                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9194                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9195                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9196                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9197                         }
9198                         dynamicvertex = true;
9199                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9200                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9201                         break;
9202                 case Q3DEFORM_BULGE:
9203                         if (!dynamicvertex)
9204                         {
9205                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9206                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9207                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9208                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9209                         }
9210                         dynamicvertex = true;
9211                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9212                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9213                         break;
9214                 case Q3DEFORM_MOVE:
9215                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9216                                 break; // if wavefunc is a nop, ignore this transform
9217                         if (!dynamicvertex)
9218                         {
9219                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9220                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9221                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9222                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9223                         }
9224                         dynamicvertex = true;
9225                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9226                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9227                         break;
9228                 }
9229         }
9230         switch(rsurface.texture->tcgen.tcgen)
9231         {
9232         default:
9233         case Q3TCGEN_TEXTURE:
9234                 break;
9235         case Q3TCGEN_LIGHTMAP:
9236                 if (!dynamicvertex)
9237                 {
9238                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9239                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9240                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9241                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9242                 }
9243                 dynamicvertex = true;
9244                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9245                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9246                 break;
9247         case Q3TCGEN_VECTOR:
9248                 if (!dynamicvertex)
9249                 {
9250                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9251                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9252                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9253                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9254                 }
9255                 dynamicvertex = true;
9256                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9257                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9258                 break;
9259         case Q3TCGEN_ENVIRONMENT:
9260                 if (!dynamicvertex)
9261                 {
9262                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9263                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9264                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9265                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9266                 }
9267                 dynamicvertex = true;
9268                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9269                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9270                 break;
9271         }
9272         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9273         {
9274                 if (!dynamicvertex)
9275                 {
9276                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9277                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9278                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9279                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9280                 }
9281                 dynamicvertex = true;
9282                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9283                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9284         }
9285
9286         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9287         {
9288                 if (!dynamicvertex)
9289                 {
9290                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9291                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9292                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9293                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9294                 }
9295                 dynamicvertex = true;
9296                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9297         }
9298
9299         // when the model data has no vertex buffer (dynamic mesh), we need to
9300         // eliminate gaps
9301         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9302                 batchneed |= BATCHNEED_NOGAPS;
9303
9304         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9305         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9306         // we ensure this by treating the vertex batch as dynamic...
9307         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9308         {
9309                 if (!dynamicvertex)
9310                 {
9311                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9312                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9313                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9314                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9315                 }
9316                 dynamicvertex = true;
9317         }
9318
9319         if (dynamicvertex)
9320         {
9321                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9322                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9323                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9324                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9325                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9326                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9327                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9328                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9329         }
9330
9331         // if needsupdate, we have to do a dynamic vertex batch for sure
9332         if (needsupdate & batchneed)
9333         {
9334                 if (!dynamicvertex)
9335                 {
9336                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9337                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9338                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9339                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9340                 }
9341                 dynamicvertex = true;
9342         }
9343
9344         // see if we need to build vertexmesh from arrays
9345         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9346         {
9347                 if (!dynamicvertex)
9348                 {
9349                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9350                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9351                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9352                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9353                 }
9354                 dynamicvertex = true;
9355         }
9356
9357         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9358         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9359                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9360
9361         rsurface.batchvertex3f = rsurface.modelvertex3f;
9362         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9363         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9364         rsurface.batchsvector3f = rsurface.modelsvector3f;
9365         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9366         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9367         rsurface.batchtvector3f = rsurface.modeltvector3f;
9368         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9369         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9370         rsurface.batchnormal3f = rsurface.modelnormal3f;
9371         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9372         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9373         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9374         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9375         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9376         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9377         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9378         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9379         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9380         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9381         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9382         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9383         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9384         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9385         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9386         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9387         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9388         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9389         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9390         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9391         rsurface.batchelement3i = rsurface.modelelement3i;
9392         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9393         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9394         rsurface.batchelement3s = rsurface.modelelement3s;
9395         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9396         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9397         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9398         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9399         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9400         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9401         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9402
9403         // if any dynamic vertex processing has to occur in software, we copy the
9404         // entire surface list together before processing to rebase the vertices
9405         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9406         //
9407         // if any gaps exist and we do not have a static vertex buffer, we have to
9408         // copy the surface list together to avoid wasting upload bandwidth on the
9409         // vertices in the gaps.
9410         //
9411         // if gaps exist and we have a static vertex buffer, we can choose whether
9412         // to combine the index buffer ranges into one dynamic index buffer or
9413         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9414         //
9415         // in many cases the batch is reduced to one draw call.
9416
9417         rsurface.batchmultidraw = false;
9418         rsurface.batchmultidrawnumsurfaces = 0;
9419         rsurface.batchmultidrawsurfacelist = NULL;
9420
9421         if (!dynamicvertex)
9422         {
9423                 // static vertex data, just set pointers...
9424                 rsurface.batchgeneratedvertex = false;
9425                 // if there are gaps, we want to build a combined index buffer,
9426                 // otherwise use the original static buffer with an appropriate offset
9427                 if (gaps)
9428                 {
9429                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9430                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9431                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9432                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9433                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9434                         {
9435                                 rsurface.batchmultidraw = true;
9436                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9437                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9438                                 return;
9439                         }
9440                         // build a new triangle elements array for this batch
9441                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9442                         rsurface.batchfirsttriangle = 0;
9443                         numtriangles = 0;
9444                         for (i = 0;i < texturenumsurfaces;i++)
9445                         {
9446                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9447                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9448                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9449                                 numtriangles += surfacenumtriangles;
9450                         }
9451                         rsurface.batchelement3i_indexbuffer = NULL;
9452                         rsurface.batchelement3i_bufferoffset = 0;
9453                         rsurface.batchelement3s = NULL;
9454                         rsurface.batchelement3s_indexbuffer = NULL;
9455                         rsurface.batchelement3s_bufferoffset = 0;
9456                         if (endvertex <= 65536)
9457                         {
9458                                 // make a 16bit (unsigned short) index array if possible
9459                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9460                                 for (i = 0;i < numtriangles*3;i++)
9461                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9462                         }
9463                         // upload buffer data for the copytriangles batch
9464                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9465                         {
9466                                 if (rsurface.batchelement3s)
9467                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9468                                 else if (rsurface.batchelement3i)
9469                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9470                         }
9471                 }
9472                 else
9473                 {
9474                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9475                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9476                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9477                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9478                 }
9479                 return;
9480         }
9481
9482         // something needs software processing, do it for real...
9483         // we only directly handle separate array data in this case and then
9484         // generate interleaved data if needed...
9485         rsurface.batchgeneratedvertex = true;
9486         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9487         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9488         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9489         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9490
9491         // now copy the vertex data into a combined array and make an index array
9492         // (this is what Quake3 does all the time)
9493         // we also apply any skeletal animation here that would have been done in
9494         // the vertex shader, because most of the dynamic vertex animation cases
9495         // need actual vertex positions and normals
9496         //if (dynamicvertex)
9497         {
9498                 rsurface.batchvertexmesh = NULL;
9499                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9500                 rsurface.batchvertexmesh_bufferoffset = 0;
9501                 rsurface.batchvertex3f = NULL;
9502                 rsurface.batchvertex3f_vertexbuffer = NULL;
9503                 rsurface.batchvertex3f_bufferoffset = 0;
9504                 rsurface.batchsvector3f = NULL;
9505                 rsurface.batchsvector3f_vertexbuffer = NULL;
9506                 rsurface.batchsvector3f_bufferoffset = 0;
9507                 rsurface.batchtvector3f = NULL;
9508                 rsurface.batchtvector3f_vertexbuffer = NULL;
9509                 rsurface.batchtvector3f_bufferoffset = 0;
9510                 rsurface.batchnormal3f = NULL;
9511                 rsurface.batchnormal3f_vertexbuffer = NULL;
9512                 rsurface.batchnormal3f_bufferoffset = 0;
9513                 rsurface.batchlightmapcolor4f = NULL;
9514                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9515                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9516                 rsurface.batchtexcoordtexture2f = NULL;
9517                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9518                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9519                 rsurface.batchtexcoordlightmap2f = NULL;
9520                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9521                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9522                 rsurface.batchskeletalindex4ub = NULL;
9523                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9524                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9525                 rsurface.batchskeletalweight4ub = NULL;
9526                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9527                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9528                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9529                 rsurface.batchelement3i_indexbuffer = NULL;
9530                 rsurface.batchelement3i_bufferoffset = 0;
9531                 rsurface.batchelement3s = NULL;
9532                 rsurface.batchelement3s_indexbuffer = NULL;
9533                 rsurface.batchelement3s_bufferoffset = 0;
9534                 rsurface.batchskeletaltransform3x4buffer = NULL;
9535                 rsurface.batchskeletaltransform3x4offset = 0;
9536                 rsurface.batchskeletaltransform3x4size = 0;
9537                 // we'll only be setting up certain arrays as needed
9538                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9539                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9540                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9541                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9542                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9543                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9544                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9545                 {
9546                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9547                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9548                 }
9549                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9550                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9551                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9552                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9553                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9554                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9555                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9556                 {
9557                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9558                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9559                 }
9560                 numvertices = 0;
9561                 numtriangles = 0;
9562                 for (i = 0;i < texturenumsurfaces;i++)
9563                 {
9564                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9565                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9566                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9567                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9568                         // copy only the data requested
9569                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9570                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9571                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9572                         {
9573                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9574                                 {
9575                                         if (rsurface.batchvertex3f)
9576                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9577                                         else
9578                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9579                                 }
9580                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9581                                 {
9582                                         if (rsurface.modelnormal3f)
9583                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9584                                         else
9585                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9586                                 }
9587                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9588                                 {
9589                                         if (rsurface.modelsvector3f)
9590                                         {
9591                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9592                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9593                                         }
9594                                         else
9595                                         {
9596                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9597                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9598                                         }
9599                                 }
9600                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9601                                 {
9602                                         if (rsurface.modellightmapcolor4f)
9603                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9604                                         else
9605                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9606                                 }
9607                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9608                                 {
9609                                         if (rsurface.modeltexcoordtexture2f)
9610                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9611                                         else
9612                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9613                                 }
9614                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9615                                 {
9616                                         if (rsurface.modeltexcoordlightmap2f)
9617                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9618                                         else
9619                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9620                                 }
9621                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9622                                 {
9623                                         if (rsurface.modelskeletalindex4ub)
9624                                         {
9625                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9626                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9627                                         }
9628                                         else
9629                                         {
9630                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9631                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9632                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9633                                                 for (j = 0;j < surfacenumvertices;j++)
9634                                                         ub[j*4] = 255;
9635                                         }
9636                                 }
9637                         }
9638                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9639                         numvertices += surfacenumvertices;
9640                         numtriangles += surfacenumtriangles;
9641                 }
9642
9643                 // generate a 16bit index array as well if possible
9644                 // (in general, dynamic batches fit)
9645                 if (numvertices <= 65536)
9646                 {
9647                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9648                         for (i = 0;i < numtriangles*3;i++)
9649                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9650                 }
9651
9652                 // since we've copied everything, the batch now starts at 0
9653                 rsurface.batchfirstvertex = 0;
9654                 rsurface.batchnumvertices = batchnumvertices;
9655                 rsurface.batchfirsttriangle = 0;
9656                 rsurface.batchnumtriangles = batchnumtriangles;
9657         }
9658
9659         // apply skeletal animation that would have been done in the vertex shader
9660         if (rsurface.batchskeletaltransform3x4)
9661         {
9662                 const unsigned char *si;
9663                 const unsigned char *sw;
9664                 const float *t[4];
9665                 const float *b = rsurface.batchskeletaltransform3x4;
9666                 float *vp, *vs, *vt, *vn;
9667                 float w[4];
9668                 float m[3][4], n[3][4];
9669                 float tp[3], ts[3], tt[3], tn[3];
9670                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9671                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9672                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9673                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9674                 si = rsurface.batchskeletalindex4ub;
9675                 sw = rsurface.batchskeletalweight4ub;
9676                 vp = rsurface.batchvertex3f;
9677                 vs = rsurface.batchsvector3f;
9678                 vt = rsurface.batchtvector3f;
9679                 vn = rsurface.batchnormal3f;
9680                 memset(m[0], 0, sizeof(m));
9681                 memset(n[0], 0, sizeof(n));
9682                 for (i = 0;i < batchnumvertices;i++)
9683                 {
9684                         t[0] = b + si[0]*12;
9685                         if (sw[0] == 255)
9686                         {
9687                                 // common case - only one matrix
9688                                 m[0][0] = t[0][ 0];
9689                                 m[0][1] = t[0][ 1];
9690                                 m[0][2] = t[0][ 2];
9691                                 m[0][3] = t[0][ 3];
9692                                 m[1][0] = t[0][ 4];
9693                                 m[1][1] = t[0][ 5];
9694                                 m[1][2] = t[0][ 6];
9695                                 m[1][3] = t[0][ 7];
9696                                 m[2][0] = t[0][ 8];
9697                                 m[2][1] = t[0][ 9];
9698                                 m[2][2] = t[0][10];
9699                                 m[2][3] = t[0][11];
9700                         }
9701                         else if (sw[2] + sw[3])
9702                         {
9703                                 // blend 4 matrices
9704                                 t[1] = b + si[1]*12;
9705                                 t[2] = b + si[2]*12;
9706                                 t[3] = b + si[3]*12;
9707                                 w[0] = sw[0] * (1.0f / 255.0f);
9708                                 w[1] = sw[1] * (1.0f / 255.0f);
9709                                 w[2] = sw[2] * (1.0f / 255.0f);
9710                                 w[3] = sw[3] * (1.0f / 255.0f);
9711                                 // blend the matrices
9712                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9713                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9714                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9715                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9716                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9717                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9718                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9719                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9720                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9721                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9722                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9723                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9724                         }
9725                         else
9726                         {
9727                                 // blend 2 matrices
9728                                 t[1] = b + si[1]*12;
9729                                 w[0] = sw[0] * (1.0f / 255.0f);
9730                                 w[1] = sw[1] * (1.0f / 255.0f);
9731                                 // blend the matrices
9732                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9733                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9734                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9735                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9736                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9737                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9738                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9739                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9740                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9741                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9742                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9743                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9744                         }
9745                         si += 4;
9746                         sw += 4;
9747                         // modify the vertex
9748                         VectorCopy(vp, tp);
9749                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9750                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9751                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9752                         vp += 3;
9753                         if (vn)
9754                         {
9755                                 // the normal transformation matrix is a set of cross products...
9756                                 CrossProduct(m[1], m[2], n[0]);
9757                                 CrossProduct(m[2], m[0], n[1]);
9758                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9759                                 VectorCopy(vn, tn);
9760                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9761                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9762                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9763                                 VectorNormalize(vn);
9764                                 vn += 3;
9765                                 if (vs)
9766                                 {
9767                                         VectorCopy(vs, ts);
9768                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9769                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9770                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9771                                         VectorNormalize(vs);
9772                                         vs += 3;
9773                                         VectorCopy(vt, tt);
9774                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9775                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9776                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9777                                         VectorNormalize(vt);
9778                                         vt += 3;
9779                                 }
9780                         }
9781                 }
9782                 rsurface.batchskeletaltransform3x4 = NULL;
9783                 rsurface.batchskeletalnumtransforms = 0;
9784         }
9785
9786         // q1bsp surfaces rendered in vertex color mode have to have colors
9787         // calculated based on lightstyles
9788         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9789         {
9790                 // generate color arrays for the surfaces in this list
9791                 int c[4];
9792                 int scale;
9793                 int size3;
9794                 const int *offsets;
9795                 const unsigned char *lm;
9796                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9797                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9798                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9799                 numvertices = 0;
9800                 for (i = 0;i < texturenumsurfaces;i++)
9801                 {
9802                         surface = texturesurfacelist[i];
9803                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9804                         surfacenumvertices = surface->num_vertices;
9805                         if (surface->lightmapinfo->samples)
9806                         {
9807                                 for (j = 0;j < surfacenumvertices;j++)
9808                                 {
9809                                         lm = surface->lightmapinfo->samples + offsets[j];
9810                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9811                                         VectorScale(lm, scale, c);
9812                                         if (surface->lightmapinfo->styles[1] != 255)
9813                                         {
9814                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9815                                                 lm += size3;
9816                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9817                                                 VectorMA(c, scale, lm, c);
9818                                                 if (surface->lightmapinfo->styles[2] != 255)
9819                                                 {
9820                                                         lm += size3;
9821                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9822                                                         VectorMA(c, scale, lm, c);
9823                                                         if (surface->lightmapinfo->styles[3] != 255)
9824                                                         {
9825                                                                 lm += size3;
9826                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9827                                                                 VectorMA(c, scale, lm, c);
9828                                                         }
9829                                                 }
9830                                         }
9831                                         c[0] >>= 7;
9832                                         c[1] >>= 7;
9833                                         c[2] >>= 7;
9834                                         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);
9835                                         numvertices++;
9836                                 }
9837                         }
9838                         else
9839                         {
9840                                 for (j = 0;j < surfacenumvertices;j++)
9841                                 {
9842                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9843                                         numvertices++;
9844                                 }
9845                         }
9846                 }
9847         }
9848
9849         // if vertices are deformed (sprite flares and things in maps, possibly
9850         // water waves, bulges and other deformations), modify the copied vertices
9851         // in place
9852         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9853         {
9854                 switch (deform->deform)
9855                 {
9856                 default:
9857                 case Q3DEFORM_PROJECTIONSHADOW:
9858                 case Q3DEFORM_TEXT0:
9859                 case Q3DEFORM_TEXT1:
9860                 case Q3DEFORM_TEXT2:
9861                 case Q3DEFORM_TEXT3:
9862                 case Q3DEFORM_TEXT4:
9863                 case Q3DEFORM_TEXT5:
9864                 case Q3DEFORM_TEXT6:
9865                 case Q3DEFORM_TEXT7:
9866                 case Q3DEFORM_NONE:
9867                         break;
9868                 case Q3DEFORM_AUTOSPRITE:
9869                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9870                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9871                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9872                         VectorNormalize(newforward);
9873                         VectorNormalize(newright);
9874                         VectorNormalize(newup);
9875 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9876 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9877 //                      rsurface.batchvertex3f_bufferoffset = 0;
9878 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9879 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9880 //                      rsurface.batchsvector3f_bufferoffset = 0;
9881 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9882 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9883 //                      rsurface.batchtvector3f_bufferoffset = 0;
9884 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9885 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9886 //                      rsurface.batchnormal3f_bufferoffset = 0;
9887                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9888                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9889                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9890                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9891                                 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);
9892                         // a single autosprite surface can contain multiple sprites...
9893                         for (j = 0;j < batchnumvertices - 3;j += 4)
9894                         {
9895                                 VectorClear(center);
9896                                 for (i = 0;i < 4;i++)
9897                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9898                                 VectorScale(center, 0.25f, center);
9899                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9900                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9901                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9902                                 for (i = 0;i < 4;i++)
9903                                 {
9904                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9905                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9906                                 }
9907                         }
9908                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9909                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9910                         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);
9911                         break;
9912                 case Q3DEFORM_AUTOSPRITE2:
9913                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9914                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9915                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9916                         VectorNormalize(newforward);
9917                         VectorNormalize(newright);
9918                         VectorNormalize(newup);
9919 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9920 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9921 //                      rsurface.batchvertex3f_bufferoffset = 0;
9922                         {
9923                                 const float *v1, *v2;
9924                                 vec3_t start, end;
9925                                 float f, l;
9926                                 struct
9927                                 {
9928                                         float length2;
9929                                         const float *v1;
9930                                         const float *v2;
9931                                 }
9932                                 shortest[2];
9933                                 memset(shortest, 0, sizeof(shortest));
9934                                 // a single autosprite surface can contain multiple sprites...
9935                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9936                                 {
9937                                         VectorClear(center);
9938                                         for (i = 0;i < 4;i++)
9939                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9940                                         VectorScale(center, 0.25f, center);
9941                                         // find the two shortest edges, then use them to define the
9942                                         // axis vectors for rotating around the central axis
9943                                         for (i = 0;i < 6;i++)
9944                                         {
9945                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9946                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9947                                                 l = VectorDistance2(v1, v2);
9948                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9949                                                 if (v1[2] != v2[2])
9950                                                         l += (1.0f / 1024.0f);
9951                                                 if (shortest[0].length2 > l || i == 0)
9952                                                 {
9953                                                         shortest[1] = shortest[0];
9954                                                         shortest[0].length2 = l;
9955                                                         shortest[0].v1 = v1;
9956                                                         shortest[0].v2 = v2;
9957                                                 }
9958                                                 else if (shortest[1].length2 > l || i == 1)
9959                                                 {
9960                                                         shortest[1].length2 = l;
9961                                                         shortest[1].v1 = v1;
9962                                                         shortest[1].v2 = v2;
9963                                                 }
9964                                         }
9965                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9966                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9967                                         // this calculates the right vector from the shortest edge
9968                                         // and the up vector from the edge midpoints
9969                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9970                                         VectorNormalize(right);
9971                                         VectorSubtract(end, start, up);
9972                                         VectorNormalize(up);
9973                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9974                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9975                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9976                                         VectorNegate(forward, forward);
9977                                         VectorReflect(forward, 0, up, forward);
9978                                         VectorNormalize(forward);
9979                                         CrossProduct(up, forward, newright);
9980                                         VectorNormalize(newright);
9981                                         // rotate the quad around the up axis vector, this is made
9982                                         // especially easy by the fact we know the quad is flat,
9983                                         // so we only have to subtract the center position and
9984                                         // measure distance along the right vector, and then
9985                                         // multiply that by the newright vector and add back the
9986                                         // center position
9987                                         // we also need to subtract the old position to undo the
9988                                         // displacement from the center, which we do with a
9989                                         // DotProduct, the subtraction/addition of center is also
9990                                         // optimized into DotProducts here
9991                                         l = DotProduct(right, center);
9992                                         for (i = 0;i < 4;i++)
9993                                         {
9994                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9995                                                 f = DotProduct(right, v1) - l;
9996                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9997                                         }
9998                                 }
9999                         }
10000                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10001                         {
10002 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10003 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10004 //                              rsurface.batchnormal3f_bufferoffset = 0;
10005                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10006                         }
10007                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10008                         {
10009 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10010 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10011 //                              rsurface.batchsvector3f_bufferoffset = 0;
10012 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10013 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10014 //                              rsurface.batchtvector3f_bufferoffset = 0;
10015                                 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);
10016                         }
10017                         break;
10018                 case Q3DEFORM_NORMAL:
10019                         // deform the normals to make reflections wavey
10020                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10021                         rsurface.batchnormal3f_vertexbuffer = NULL;
10022                         rsurface.batchnormal3f_bufferoffset = 0;
10023                         for (j = 0;j < batchnumvertices;j++)
10024                         {
10025                                 float vertex[3];
10026                                 float *normal = rsurface.batchnormal3f + 3*j;
10027                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10028                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10029                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10030                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10031                                 VectorNormalize(normal);
10032                         }
10033                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10034                         {
10035 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10036 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10037 //                              rsurface.batchsvector3f_bufferoffset = 0;
10038 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10039 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10040 //                              rsurface.batchtvector3f_bufferoffset = 0;
10041                                 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);
10042                         }
10043                         break;
10044                 case Q3DEFORM_WAVE:
10045                         // deform vertex array to make wavey water and flags and such
10046                         waveparms[0] = deform->waveparms[0];
10047                         waveparms[1] = deform->waveparms[1];
10048                         waveparms[2] = deform->waveparms[2];
10049                         waveparms[3] = deform->waveparms[3];
10050                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10051                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10052                         // this is how a divisor of vertex influence on deformation
10053                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10054                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10055 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10056 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10057 //                      rsurface.batchvertex3f_bufferoffset = 0;
10058 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10059 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10060 //                      rsurface.batchnormal3f_bufferoffset = 0;
10061                         for (j = 0;j < batchnumvertices;j++)
10062                         {
10063                                 // if the wavefunc depends on time, evaluate it per-vertex
10064                                 if (waveparms[3])
10065                                 {
10066                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10067                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10068                                 }
10069                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10070                         }
10071                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10072                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10073                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10074                         {
10075 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10076 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10077 //                              rsurface.batchsvector3f_bufferoffset = 0;
10078 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10079 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10080 //                              rsurface.batchtvector3f_bufferoffset = 0;
10081                                 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);
10082                         }
10083                         break;
10084                 case Q3DEFORM_BULGE:
10085                         // deform vertex array to make the surface have moving bulges
10086 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10087 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10088 //                      rsurface.batchvertex3f_bufferoffset = 0;
10089 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10090 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10091 //                      rsurface.batchnormal3f_bufferoffset = 0;
10092                         for (j = 0;j < batchnumvertices;j++)
10093                         {
10094                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10095                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10096                         }
10097                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10098                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10099                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10100                         {
10101 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10102 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10103 //                              rsurface.batchsvector3f_bufferoffset = 0;
10104 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10105 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10106 //                              rsurface.batchtvector3f_bufferoffset = 0;
10107                                 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);
10108                         }
10109                         break;
10110                 case Q3DEFORM_MOVE:
10111                         // deform vertex array
10112                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10113                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10114                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10115                         VectorScale(deform->parms, scale, waveparms);
10116 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10117 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10118 //                      rsurface.batchvertex3f_bufferoffset = 0;
10119                         for (j = 0;j < batchnumvertices;j++)
10120                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10121                         break;
10122                 }
10123         }
10124
10125         if (rsurface.batchtexcoordtexture2f)
10126         {
10127         // generate texcoords based on the chosen texcoord source
10128                 switch(rsurface.texture->tcgen.tcgen)
10129                 {
10130                 default:
10131                 case Q3TCGEN_TEXTURE:
10132                         break;
10133                 case Q3TCGEN_LIGHTMAP:
10134         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10135         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10136         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10137                         if (rsurface.batchtexcoordlightmap2f)
10138                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10139                         break;
10140                 case Q3TCGEN_VECTOR:
10141         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10142         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10143         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10144                         for (j = 0;j < batchnumvertices;j++)
10145                         {
10146                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10147                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10148                         }
10149                         break;
10150                 case Q3TCGEN_ENVIRONMENT:
10151                         // make environment reflections using a spheremap
10152                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10153                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10154                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10155                         for (j = 0;j < batchnumvertices;j++)
10156                         {
10157                                 // identical to Q3A's method, but executed in worldspace so
10158                                 // carried models can be shiny too
10159
10160                                 float viewer[3], d, reflected[3], worldreflected[3];
10161
10162                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10163                                 // VectorNormalize(viewer);
10164
10165                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10166
10167                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10168                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10169                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10170                                 // note: this is proportinal to viewer, so we can normalize later
10171
10172                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10173                                 VectorNormalize(worldreflected);
10174
10175                                 // note: this sphere map only uses world x and z!
10176                                 // so positive and negative y will LOOK THE SAME.
10177                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10178                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10179                         }
10180                         break;
10181                 }
10182                 // the only tcmod that needs software vertex processing is turbulent, so
10183                 // check for it here and apply the changes if needed
10184                 // and we only support that as the first one
10185                 // (handling a mixture of turbulent and other tcmods would be problematic
10186                 //  without punting it entirely to a software path)
10187                 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10188                 {
10189                         amplitude = rsurface.texture->tcmods[0].parms[1];
10190                         animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10191         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10192         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10193         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10194                         for (j = 0;j < batchnumvertices;j++)
10195                         {
10196                                 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);
10197                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10198                         }
10199                 }
10200         }
10201
10202         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10203         {
10204                 // convert the modified arrays to vertex structs
10205 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10206 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10207 //              rsurface.batchvertexmesh_bufferoffset = 0;
10208                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10209                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10210                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10211                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10212                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10213                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10214                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10215                 {
10216                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10217                         {
10218                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10219                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10220                         }
10221                 }
10222                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10223                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10224                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10225                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10226                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10227                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10228                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10229                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10230                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10231                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10232                 {
10233                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10234                         {
10235                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10236                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10237                         }
10238                 }
10239         }
10240
10241         // upload buffer data for the dynamic batch
10242         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10243         {
10244                 if (rsurface.batchvertexmesh)
10245                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10246                 else
10247                 {
10248                         if (rsurface.batchvertex3f)
10249                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10250                         if (rsurface.batchsvector3f)
10251                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10252                         if (rsurface.batchtvector3f)
10253                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10254                         if (rsurface.batchnormal3f)
10255                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10256                         if (rsurface.batchlightmapcolor4f)
10257                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10258                         if (rsurface.batchtexcoordtexture2f)
10259                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10260                         if (rsurface.batchtexcoordlightmap2f)
10261                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10262                         if (rsurface.batchskeletalindex4ub)
10263                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10264                         if (rsurface.batchskeletalweight4ub)
10265                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10266                 }
10267                 if (rsurface.batchelement3s)
10268                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10269                 else if (rsurface.batchelement3i)
10270                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10271         }
10272 }
10273
10274 void RSurf_DrawBatch(void)
10275 {
10276         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10277         // through the pipeline, killing it earlier in the pipeline would have
10278         // per-surface overhead rather than per-batch overhead, so it's best to
10279         // reject it here, before it hits glDraw.
10280         if (rsurface.batchnumtriangles == 0)
10281                 return;
10282 #if 0
10283         // batch debugging code
10284         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10285         {
10286                 int i;
10287                 int j;
10288                 int c;
10289                 const int *e;
10290                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10291                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10292                 {
10293                         c = e[i];
10294                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10295                         {
10296                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10297                                 {
10298                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10299                                                 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);
10300                                         break;
10301                                 }
10302                         }
10303                 }
10304         }
10305 #endif
10306         if (rsurface.batchmultidraw)
10307         {
10308                 // issue multiple draws rather than copying index data
10309                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10310                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10311                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10312                 for (i = 0;i < numsurfaces;)
10313                 {
10314                         // combine consecutive surfaces as one draw
10315                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10316                                 if (surfacelist[j] != surfacelist[k] + 1)
10317                                         break;
10318                         firstvertex = surfacelist[i]->num_firstvertex;
10319                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10320                         firsttriangle = surfacelist[i]->num_firsttriangle;
10321                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10322                         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);
10323                         i = j;
10324                 }
10325         }
10326         else
10327         {
10328                 // there is only one consecutive run of index data (may have been combined)
10329                 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);
10330         }
10331 }
10332
10333 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10334 {
10335         // pick the closest matching water plane
10336         int planeindex, vertexindex, bestplaneindex = -1;
10337         float d, bestd;
10338         vec3_t vert;
10339         const float *v;
10340         r_waterstate_waterplane_t *p;
10341         qboolean prepared = false;
10342         bestd = 0;
10343         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10344         {
10345                 if(p->camera_entity != rsurface.texture->camera_entity)
10346                         continue;
10347                 d = 0;
10348                 if(!prepared)
10349                 {
10350                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10351                         prepared = true;
10352                         if(rsurface.batchnumvertices == 0)
10353                                 break;
10354                 }
10355                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10356                 {
10357                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10358                         d += fabs(PlaneDiff(vert, &p->plane));
10359                 }
10360                 if (bestd > d || bestplaneindex < 0)
10361                 {
10362                         bestd = d;
10363                         bestplaneindex = planeindex;
10364                 }
10365         }
10366         return bestplaneindex;
10367         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10368         // this situation though, as it might be better to render single larger
10369         // batches with useless stuff (backface culled for example) than to
10370         // render multiple smaller batches
10371 }
10372
10373 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10374 {
10375         int i;
10376         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10377         rsurface.passcolor4f_vertexbuffer = 0;
10378         rsurface.passcolor4f_bufferoffset = 0;
10379         for (i = 0;i < rsurface.batchnumvertices;i++)
10380                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10381 }
10382
10383 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10384 {
10385         int i;
10386         float f;
10387         const float *v;
10388         const float *c;
10389         float *c2;
10390         if (rsurface.passcolor4f)
10391         {
10392                 // generate color arrays
10393                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10394                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10395                 rsurface.passcolor4f_vertexbuffer = 0;
10396                 rsurface.passcolor4f_bufferoffset = 0;
10397                 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)
10398                 {
10399                         f = RSurf_FogVertex(v);
10400                         c2[0] = c[0] * f;
10401                         c2[1] = c[1] * f;
10402                         c2[2] = c[2] * f;
10403                         c2[3] = c[3];
10404                 }
10405         }
10406         else
10407         {
10408                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10409                 rsurface.passcolor4f_vertexbuffer = 0;
10410                 rsurface.passcolor4f_bufferoffset = 0;
10411                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10412                 {
10413                         f = RSurf_FogVertex(v);
10414                         c2[0] = f;
10415                         c2[1] = f;
10416                         c2[2] = f;
10417                         c2[3] = 1;
10418                 }
10419         }
10420 }
10421
10422 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10423 {
10424         int i;
10425         float f;
10426         const float *v;
10427         const float *c;
10428         float *c2;
10429         if (!rsurface.passcolor4f)
10430                 return;
10431         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10432         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10433         rsurface.passcolor4f_vertexbuffer = 0;
10434         rsurface.passcolor4f_bufferoffset = 0;
10435         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)
10436         {
10437                 f = RSurf_FogVertex(v);
10438                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10439                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10440                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10441                 c2[3] = c[3];
10442         }
10443 }
10444
10445 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10446 {
10447         int i;
10448         const float *c;
10449         float *c2;
10450         if (!rsurface.passcolor4f)
10451                 return;
10452         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10453         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10454         rsurface.passcolor4f_vertexbuffer = 0;
10455         rsurface.passcolor4f_bufferoffset = 0;
10456         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10457         {
10458                 c2[0] = c[0] * r;
10459                 c2[1] = c[1] * g;
10460                 c2[2] = c[2] * b;
10461                 c2[3] = c[3] * a;
10462         }
10463 }
10464
10465 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10466 {
10467         int i;
10468         const float *c;
10469         float *c2;
10470         if (!rsurface.passcolor4f)
10471                 return;
10472         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10473         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10474         rsurface.passcolor4f_vertexbuffer = 0;
10475         rsurface.passcolor4f_bufferoffset = 0;
10476         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10477         {
10478                 c2[0] = c[0] + r_refdef.scene.ambient;
10479                 c2[1] = c[1] + r_refdef.scene.ambient;
10480                 c2[2] = c[2] + r_refdef.scene.ambient;
10481                 c2[3] = c[3];
10482         }
10483 }
10484
10485 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10486 {
10487         // TODO: optimize
10488         rsurface.passcolor4f = NULL;
10489         rsurface.passcolor4f_vertexbuffer = 0;
10490         rsurface.passcolor4f_bufferoffset = 0;
10491         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10492         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10493         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10494         GL_Color(r, g, b, a);
10495         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10496         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10497         R_Mesh_TexMatrix(0, NULL);
10498         RSurf_DrawBatch();
10499 }
10500
10501 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10502 {
10503         // TODO: optimize applyfog && applycolor case
10504         // just apply fog if necessary, and tint the fog color array if necessary
10505         rsurface.passcolor4f = NULL;
10506         rsurface.passcolor4f_vertexbuffer = 0;
10507         rsurface.passcolor4f_bufferoffset = 0;
10508         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10509         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10510         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10511         GL_Color(r, g, b, a);
10512         RSurf_DrawBatch();
10513 }
10514
10515 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10516 {
10517         // TODO: optimize
10518         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10519         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10520         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10521         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10522         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10523         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10524         GL_Color(r, g, b, a);
10525         RSurf_DrawBatch();
10526 }
10527
10528 static void RSurf_DrawBatch_GL11_ClampColor(void)
10529 {
10530         int i;
10531         const float *c1;
10532         float *c2;
10533         if (!rsurface.passcolor4f)
10534                 return;
10535         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10536         {
10537                 c2[0] = bound(0.0f, c1[0], 1.0f);
10538                 c2[1] = bound(0.0f, c1[1], 1.0f);
10539                 c2[2] = bound(0.0f, c1[2], 1.0f);
10540                 c2[3] = bound(0.0f, c1[3], 1.0f);
10541         }
10542 }
10543
10544 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10545 {
10546         int i;
10547         float f;
10548         const float *v;
10549         const float *n;
10550         float *c;
10551         //vec3_t eyedir;
10552
10553         // fake shading
10554         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10555         rsurface.passcolor4f_vertexbuffer = 0;
10556         rsurface.passcolor4f_bufferoffset = 0;
10557         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)
10558         {
10559                 f = -DotProduct(r_refdef.view.forward, n);
10560                 f = max(0, f);
10561                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10562                 f *= r_refdef.lightmapintensity;
10563                 Vector4Set(c, f, f, f, 1);
10564         }
10565 }
10566
10567 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10568 {
10569         RSurf_DrawBatch_GL11_ApplyFakeLight();
10570         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10571         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10572         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10573         GL_Color(r, g, b, a);
10574         RSurf_DrawBatch();
10575 }
10576
10577 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10578 {
10579         int i;
10580         float f;
10581         float alpha;
10582         const float *v;
10583         const float *n;
10584         float *c;
10585         vec3_t ambientcolor;
10586         vec3_t diffusecolor;
10587         vec3_t lightdir;
10588         // TODO: optimize
10589         // model lighting
10590         VectorCopy(rsurface.modellight_lightdir, lightdir);
10591         f = 0.5f * r_refdef.lightmapintensity;
10592         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10593         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10594         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10595         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10596         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10597         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10598         alpha = *a;
10599         if (VectorLength2(diffusecolor) > 0)
10600         {
10601                 // q3-style directional shading
10602                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10603                 rsurface.passcolor4f_vertexbuffer = 0;
10604                 rsurface.passcolor4f_bufferoffset = 0;
10605                 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)
10606                 {
10607                         if ((f = DotProduct(n, lightdir)) > 0)
10608                                 VectorMA(ambientcolor, f, diffusecolor, c);
10609                         else
10610                                 VectorCopy(ambientcolor, c);
10611                         c[3] = alpha;
10612                 }
10613                 *r = 1;
10614                 *g = 1;
10615                 *b = 1;
10616                 *a = 1;
10617                 *applycolor = false;
10618         }
10619         else
10620         {
10621                 *r = ambientcolor[0];
10622                 *g = ambientcolor[1];
10623                 *b = ambientcolor[2];
10624                 rsurface.passcolor4f = NULL;
10625                 rsurface.passcolor4f_vertexbuffer = 0;
10626                 rsurface.passcolor4f_bufferoffset = 0;
10627         }
10628 }
10629
10630 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10631 {
10632         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10633         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10634         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10635         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10636         GL_Color(r, g, b, a);
10637         RSurf_DrawBatch();
10638 }
10639
10640 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10641 {
10642         int i;
10643         float f;
10644         const float *v;
10645         float *c;
10646
10647         // fake shading
10648         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10649         rsurface.passcolor4f_vertexbuffer = 0;
10650         rsurface.passcolor4f_bufferoffset = 0;
10651
10652         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10653         {
10654                 f = 1 - RSurf_FogVertex(v);
10655                 c[0] = r;
10656                 c[1] = g;
10657                 c[2] = b;
10658                 c[3] = f * a;
10659         }
10660 }
10661
10662 void RSurf_SetupDepthAndCulling(void)
10663 {
10664         // submodels are biased to avoid z-fighting with world surfaces that they
10665         // may be exactly overlapping (avoids z-fighting artifacts on certain
10666         // doors and things in Quake maps)
10667         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10668         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10669         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10670         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10671 }
10672
10673 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10674 {
10675         // transparent sky would be ridiculous
10676         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10677                 return;
10678         R_SetupShader_Generic_NoTexture(false, false);
10679         skyrenderlater = true;
10680         RSurf_SetupDepthAndCulling();
10681         GL_DepthMask(true);
10682         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10683         // skymasking on them, and Quake3 never did sky masking (unlike
10684         // software Quake and software Quake2), so disable the sky masking
10685         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10686         // and skymasking also looks very bad when noclipping outside the
10687         // level, so don't use it then either.
10688         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10689         {
10690                 R_Mesh_ResetTextureState();
10691                 if (skyrendermasked)
10692                 {
10693                         R_SetupShader_DepthOrShadow(false, false, false);
10694                         // depth-only (masking)
10695                         GL_ColorMask(0,0,0,0);
10696                         // just to make sure that braindead drivers don't draw
10697                         // anything despite that colormask...
10698                         GL_BlendFunc(GL_ZERO, GL_ONE);
10699                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10700                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10701                 }
10702                 else
10703                 {
10704                         R_SetupShader_Generic_NoTexture(false, false);
10705                         // fog sky
10706                         GL_BlendFunc(GL_ONE, GL_ZERO);
10707                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10708                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10709                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10710                 }
10711                 RSurf_DrawBatch();
10712                 if (skyrendermasked)
10713                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10714         }
10715         R_Mesh_ResetTextureState();
10716         GL_Color(1, 1, 1, 1);
10717 }
10718
10719 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10720 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10721 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10722 {
10723         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10724                 return;
10725         if (prepass)
10726         {
10727                 // render screenspace normalmap to texture
10728                 GL_DepthMask(true);
10729                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10730                 RSurf_DrawBatch();
10731                 return;
10732         }
10733
10734         // bind lightmap texture
10735
10736         // water/refraction/reflection/camera surfaces have to be handled specially
10737         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10738         {
10739                 int start, end, startplaneindex;
10740                 for (start = 0;start < texturenumsurfaces;start = end)
10741                 {
10742                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10743                         if(startplaneindex < 0)
10744                         {
10745                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10746                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10747                                 end = start + 1;
10748                                 continue;
10749                         }
10750                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10751                                 ;
10752                         // now that we have a batch using the same planeindex, render it
10753                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10754                         {
10755                                 // render water or distortion background
10756                                 GL_DepthMask(true);
10757                                 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);
10758                                 RSurf_DrawBatch();
10759                                 // blend surface on top
10760                                 GL_DepthMask(false);
10761                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10762                                 RSurf_DrawBatch();
10763                         }
10764                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10765                         {
10766                                 // render surface with reflection texture as input
10767                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10768                                 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);
10769                                 RSurf_DrawBatch();
10770                         }
10771                 }
10772                 return;
10773         }
10774
10775         // render surface batch normally
10776         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10777         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);
10778         RSurf_DrawBatch();
10779 }
10780
10781 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10782 {
10783         // OpenGL 1.3 path - anything not completely ancient
10784         qboolean applycolor;
10785         qboolean applyfog;
10786         int layerindex;
10787         const texturelayer_t *layer;
10788         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);
10789         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10790
10791         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10792         {
10793                 vec4_t layercolor;
10794                 int layertexrgbscale;
10795                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10796                 {
10797                         if (layerindex == 0)
10798                                 GL_AlphaTest(true);
10799                         else
10800                         {
10801                                 GL_AlphaTest(false);
10802                                 GL_DepthFunc(GL_EQUAL);
10803                         }
10804                 }
10805                 GL_DepthMask(layer->depthmask && writedepth);
10806                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10807                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10808                 {
10809                         layertexrgbscale = 4;
10810                         VectorScale(layer->color, 0.25f, layercolor);
10811                 }
10812                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10813                 {
10814                         layertexrgbscale = 2;
10815                         VectorScale(layer->color, 0.5f, layercolor);
10816                 }
10817                 else
10818                 {
10819                         layertexrgbscale = 1;
10820                         VectorScale(layer->color, 1.0f, layercolor);
10821                 }
10822                 layercolor[3] = layer->color[3];
10823                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10824                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10825                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10826                 switch (layer->type)
10827                 {
10828                 case TEXTURELAYERTYPE_LITTEXTURE:
10829                         // single-pass lightmapped texture with 2x rgbscale
10830                         R_Mesh_TexBind(0, r_texture_white);
10831                         R_Mesh_TexMatrix(0, NULL);
10832                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10833                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10834                         R_Mesh_TexBind(1, layer->texture);
10835                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10836                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10837                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10838                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10839                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10840                         else if (FAKELIGHT_ENABLED)
10841                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10842                         else if (rsurface.uselightmaptexture)
10843                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10844                         else
10845                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10846                         break;
10847                 case TEXTURELAYERTYPE_TEXTURE:
10848                         // singletexture unlit texture with transparency support
10849                         R_Mesh_TexBind(0, layer->texture);
10850                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10851                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10852                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10853                         R_Mesh_TexBind(1, 0);
10854                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10855                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10856                         break;
10857                 case TEXTURELAYERTYPE_FOG:
10858                         // singletexture fogging
10859                         if (layer->texture)
10860                         {
10861                                 R_Mesh_TexBind(0, layer->texture);
10862                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10863                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10864                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10865                         }
10866                         else
10867                         {
10868                                 R_Mesh_TexBind(0, 0);
10869                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10870                         }
10871                         R_Mesh_TexBind(1, 0);
10872                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10873                         // generate a color array for the fog pass
10874                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10875                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10876                         RSurf_DrawBatch();
10877                         break;
10878                 default:
10879                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10880                 }
10881         }
10882         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10883         {
10884                 GL_DepthFunc(GL_LEQUAL);
10885                 GL_AlphaTest(false);
10886         }
10887 }
10888
10889 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10890 {
10891         // OpenGL 1.1 - crusty old voodoo path
10892         qboolean applyfog;
10893         int layerindex;
10894         const texturelayer_t *layer;
10895         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);
10896         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10897
10898         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10899         {
10900                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10901                 {
10902                         if (layerindex == 0)
10903                                 GL_AlphaTest(true);
10904                         else
10905                         {
10906                                 GL_AlphaTest(false);
10907                                 GL_DepthFunc(GL_EQUAL);
10908                         }
10909                 }
10910                 GL_DepthMask(layer->depthmask && writedepth);
10911                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10912                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10913                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10914                 switch (layer->type)
10915                 {
10916                 case TEXTURELAYERTYPE_LITTEXTURE:
10917                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10918                         {
10919                                 // two-pass lit texture with 2x rgbscale
10920                                 // first the lightmap pass
10921                                 R_Mesh_TexBind(0, r_texture_white);
10922                                 R_Mesh_TexMatrix(0, NULL);
10923                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10924                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10925                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10926                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10927                                 else if (FAKELIGHT_ENABLED)
10928                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10929                                 else if (rsurface.uselightmaptexture)
10930                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10931                                 else
10932                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10933                                 // then apply the texture to it
10934                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10935                                 R_Mesh_TexBind(0, layer->texture);
10936                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10937                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10938                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10939                                 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);
10940                         }
10941                         else
10942                         {
10943                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10944                                 R_Mesh_TexBind(0, layer->texture);
10945                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10946                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10947                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10948                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10949                                         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);
10950                                 else if (FAKELIGHT_ENABLED)
10951                                         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);
10952                                 else
10953                                         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);
10954                         }
10955                         break;
10956                 case TEXTURELAYERTYPE_TEXTURE:
10957                         // singletexture unlit texture with transparency support
10958                         R_Mesh_TexBind(0, layer->texture);
10959                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10960                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10961                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10962                         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);
10963                         break;
10964                 case TEXTURELAYERTYPE_FOG:
10965                         // singletexture fogging
10966                         if (layer->texture)
10967                         {
10968                                 R_Mesh_TexBind(0, layer->texture);
10969                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10970                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10971                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10972                         }
10973                         else
10974                         {
10975                                 R_Mesh_TexBind(0, 0);
10976                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10977                         }
10978                         // generate a color array for the fog pass
10979                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10980                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10981                         RSurf_DrawBatch();
10982                         break;
10983                 default:
10984                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10985                 }
10986         }
10987         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10988         {
10989                 GL_DepthFunc(GL_LEQUAL);
10990                 GL_AlphaTest(false);
10991         }
10992 }
10993
10994 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10995 {
10996         int vi;
10997         int j;
10998         r_vertexgeneric_t *batchvertex;
10999         float c[4];
11000
11001 //      R_Mesh_ResetTextureState();
11002         R_SetupShader_Generic_NoTexture(false, false);
11003
11004         if(rsurface.texture && rsurface.texture->currentskinframe)
11005         {
11006                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11007                 c[3] *= rsurface.texture->currentalpha;
11008         }
11009         else
11010         {
11011                 c[0] = 1;
11012                 c[1] = 0;
11013                 c[2] = 1;
11014                 c[3] = 1;
11015         }
11016
11017         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11018         {
11019                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11020                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11021                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11022         }
11023
11024         // brighten it up (as texture value 127 means "unlit")
11025         c[0] *= 2 * r_refdef.view.colorscale;
11026         c[1] *= 2 * r_refdef.view.colorscale;
11027         c[2] *= 2 * r_refdef.view.colorscale;
11028
11029         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11030                 c[3] *= r_wateralpha.value;
11031
11032         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11033         {
11034                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11035                 GL_DepthMask(false);
11036         }
11037         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11038         {
11039                 GL_BlendFunc(GL_ONE, GL_ONE);
11040                 GL_DepthMask(false);
11041         }
11042         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11043         {
11044                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11045                 GL_DepthMask(false);
11046         }
11047         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11048         {
11049                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11050                 GL_DepthMask(false);
11051         }
11052         else
11053         {
11054                 GL_BlendFunc(GL_ONE, GL_ZERO);
11055                 GL_DepthMask(writedepth);
11056         }
11057
11058         if (r_showsurfaces.integer == 3)
11059         {
11060                 rsurface.passcolor4f = NULL;
11061
11062                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11063                 {
11064                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11065
11066                         rsurface.passcolor4f = NULL;
11067                         rsurface.passcolor4f_vertexbuffer = 0;
11068                         rsurface.passcolor4f_bufferoffset = 0;
11069                 }
11070                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11071                 {
11072                         qboolean applycolor = true;
11073                         float one = 1.0;
11074
11075                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11076
11077                         r_refdef.lightmapintensity = 1;
11078                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11079                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11080                 }
11081                 else if (FAKELIGHT_ENABLED)
11082                 {
11083                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11084
11085                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11086                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11087                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11088                 }
11089                 else
11090                 {
11091                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11092
11093                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11094                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11095                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11096                 }
11097
11098                 if(!rsurface.passcolor4f)
11099                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11100
11101                 RSurf_DrawBatch_GL11_ApplyAmbient();
11102                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11103                 if(r_refdef.fogenabled)
11104                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11105                 RSurf_DrawBatch_GL11_ClampColor();
11106
11107                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11108                 R_SetupShader_Generic_NoTexture(false, false);
11109                 RSurf_DrawBatch();
11110         }
11111         else if (!r_refdef.view.showdebug)
11112         {
11113                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11114                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11115                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11116                 {
11117                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11118                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11119                 }
11120                 R_Mesh_PrepareVertices_Generic_Unlock();
11121                 RSurf_DrawBatch();
11122         }
11123         else if (r_showsurfaces.integer == 4)
11124         {
11125                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11126                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11127                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11128                 {
11129                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11130                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11131                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11132                 }
11133                 R_Mesh_PrepareVertices_Generic_Unlock();
11134                 RSurf_DrawBatch();
11135         }
11136         else if (r_showsurfaces.integer == 2)
11137         {
11138                 const int *e;
11139                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11140                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11141                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11142                 {
11143                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11144                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11145                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11146                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11147                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11148                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11149                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11150                 }
11151                 R_Mesh_PrepareVertices_Generic_Unlock();
11152                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11153         }
11154         else
11155         {
11156                 int texturesurfaceindex;
11157                 int k;
11158                 const msurface_t *surface;
11159                 float surfacecolor4f[4];
11160                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11161                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11162                 vi = 0;
11163                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11164                 {
11165                         surface = texturesurfacelist[texturesurfaceindex];
11166                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11167                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11168                         for (j = 0;j < surface->num_vertices;j++)
11169                         {
11170                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11171                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11172                                 vi++;
11173                         }
11174                 }
11175                 R_Mesh_PrepareVertices_Generic_Unlock();
11176                 RSurf_DrawBatch();
11177         }
11178 }
11179
11180 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11181 {
11182         CHECKGLERROR
11183         RSurf_SetupDepthAndCulling();
11184         if (r_showsurfaces.integer)
11185         {
11186                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11187                 return;
11188         }
11189         switch (vid.renderpath)
11190         {
11191         case RENDERPATH_GL20:
11192         case RENDERPATH_D3D9:
11193         case RENDERPATH_D3D10:
11194         case RENDERPATH_D3D11:
11195         case RENDERPATH_SOFT:
11196         case RENDERPATH_GLES2:
11197                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11198                 break;
11199         case RENDERPATH_GL13:
11200         case RENDERPATH_GLES1:
11201                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11202                 break;
11203         case RENDERPATH_GL11:
11204                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11205                 break;
11206         }
11207         CHECKGLERROR
11208 }
11209
11210 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11211 {
11212         CHECKGLERROR
11213         RSurf_SetupDepthAndCulling();
11214         if (r_showsurfaces.integer)
11215         {
11216                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11217                 return;
11218         }
11219         switch (vid.renderpath)
11220         {
11221         case RENDERPATH_GL20:
11222         case RENDERPATH_D3D9:
11223         case RENDERPATH_D3D10:
11224         case RENDERPATH_D3D11:
11225         case RENDERPATH_SOFT:
11226         case RENDERPATH_GLES2:
11227                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11228                 break;
11229         case RENDERPATH_GL13:
11230         case RENDERPATH_GLES1:
11231                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11232                 break;
11233         case RENDERPATH_GL11:
11234                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11235                 break;
11236         }
11237         CHECKGLERROR
11238 }
11239
11240 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11241 {
11242         int i, j;
11243         int texturenumsurfaces, endsurface;
11244         texture_t *texture;
11245         const msurface_t *surface;
11246         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11247
11248         // if the model is static it doesn't matter what value we give for
11249         // wantnormals and wanttangents, so this logic uses only rules applicable
11250         // to a model, knowing that they are meaningless otherwise
11251         if (ent == r_refdef.scene.worldentity)
11252                 RSurf_ActiveWorldEntity();
11253         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11254                 RSurf_ActiveModelEntity(ent, false, false, false);
11255         else
11256         {
11257                 switch (vid.renderpath)
11258                 {
11259                 case RENDERPATH_GL20:
11260                 case RENDERPATH_D3D9:
11261                 case RENDERPATH_D3D10:
11262                 case RENDERPATH_D3D11:
11263                 case RENDERPATH_SOFT:
11264                 case RENDERPATH_GLES2:
11265                         RSurf_ActiveModelEntity(ent, true, true, false);
11266                         break;
11267                 case RENDERPATH_GL11:
11268                 case RENDERPATH_GL13:
11269                 case RENDERPATH_GLES1:
11270                         RSurf_ActiveModelEntity(ent, true, false, false);
11271                         break;
11272                 }
11273         }
11274
11275         if (r_transparentdepthmasking.integer)
11276         {
11277                 qboolean setup = false;
11278                 for (i = 0;i < numsurfaces;i = j)
11279                 {
11280                         j = i + 1;
11281                         surface = rsurface.modelsurfaces + surfacelist[i];
11282                         texture = surface->texture;
11283                         rsurface.texture = R_GetCurrentTexture(texture);
11284                         rsurface.lightmaptexture = NULL;
11285                         rsurface.deluxemaptexture = NULL;
11286                         rsurface.uselightmaptexture = false;
11287                         // scan ahead until we find a different texture
11288                         endsurface = min(i + 1024, numsurfaces);
11289                         texturenumsurfaces = 0;
11290                         texturesurfacelist[texturenumsurfaces++] = surface;
11291                         for (;j < endsurface;j++)
11292                         {
11293                                 surface = rsurface.modelsurfaces + surfacelist[j];
11294                                 if (texture != surface->texture)
11295                                         break;
11296                                 texturesurfacelist[texturenumsurfaces++] = surface;
11297                         }
11298                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11299                                 continue;
11300                         // render the range of surfaces as depth
11301                         if (!setup)
11302                         {
11303                                 setup = true;
11304                                 GL_ColorMask(0,0,0,0);
11305                                 GL_Color(1,1,1,1);
11306                                 GL_DepthTest(true);
11307                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11308                                 GL_DepthMask(true);
11309 //                              R_Mesh_ResetTextureState();
11310                         }
11311                         RSurf_SetupDepthAndCulling();
11312                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11313                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11314                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11315                         RSurf_DrawBatch();
11316                 }
11317                 if (setup)
11318                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11319         }
11320
11321         for (i = 0;i < numsurfaces;i = j)
11322         {
11323                 j = i + 1;
11324                 surface = rsurface.modelsurfaces + surfacelist[i];
11325                 texture = surface->texture;
11326                 rsurface.texture = R_GetCurrentTexture(texture);
11327                 // scan ahead until we find a different texture
11328                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11329                 texturenumsurfaces = 0;
11330                 texturesurfacelist[texturenumsurfaces++] = surface;
11331                 if(FAKELIGHT_ENABLED)
11332                 {
11333                         rsurface.lightmaptexture = NULL;
11334                         rsurface.deluxemaptexture = NULL;
11335                         rsurface.uselightmaptexture = false;
11336                         for (;j < endsurface;j++)
11337                         {
11338                                 surface = rsurface.modelsurfaces + surfacelist[j];
11339                                 if (texture != surface->texture)
11340                                         break;
11341                                 texturesurfacelist[texturenumsurfaces++] = surface;
11342                         }
11343                 }
11344                 else
11345                 {
11346                         rsurface.lightmaptexture = surface->lightmaptexture;
11347                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11348                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11349                         for (;j < endsurface;j++)
11350                         {
11351                                 surface = rsurface.modelsurfaces + surfacelist[j];
11352                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11353                                         break;
11354                                 texturesurfacelist[texturenumsurfaces++] = surface;
11355                         }
11356                 }
11357                 // render the range of surfaces
11358                 if (ent == r_refdef.scene.worldentity)
11359                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11360                 else
11361                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11362         }
11363         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11364 }
11365
11366 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11367 {
11368         // transparent surfaces get pushed off into the transparent queue
11369         int surfacelistindex;
11370         const msurface_t *surface;
11371         vec3_t tempcenter, center;
11372         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11373         {
11374                 surface = texturesurfacelist[surfacelistindex];
11375                 if (r_transparent_sortsurfacesbynearest.integer)
11376                 {
11377                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11378                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11379                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11380                 }
11381                 else
11382                 {
11383                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11384                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11385                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11386                 }
11387                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11388                 if (rsurface.entity->transparent_offset) // transparent offset
11389                 {
11390                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11391                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11392                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11393                 }
11394                 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);
11395         }
11396 }
11397
11398 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11399 {
11400         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11401                 return;
11402         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11403                 return;
11404         RSurf_SetupDepthAndCulling();
11405         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11406         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11407         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11408         RSurf_DrawBatch();
11409 }
11410
11411 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11412 {
11413         CHECKGLERROR
11414         if (depthonly)
11415                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11416         else if (prepass)
11417         {
11418                 if (!rsurface.texture->currentnumlayers)
11419                         return;
11420                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11421                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11422                 else
11423                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11424         }
11425         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11426                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11427         else if (!rsurface.texture->currentnumlayers)
11428                 return;
11429         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11430         {
11431                 // in the deferred case, transparent surfaces were queued during prepass
11432                 if (!r_shadow_usingdeferredprepass)
11433                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11434         }
11435         else
11436         {
11437                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11438                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11439         }
11440         CHECKGLERROR
11441 }
11442
11443 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11444 {
11445         int i, j;
11446         texture_t *texture;
11447         R_FrameData_SetMark();
11448         // break the surface list down into batches by texture and use of lightmapping
11449         for (i = 0;i < numsurfaces;i = j)
11450         {
11451                 j = i + 1;
11452                 // texture is the base texture pointer, rsurface.texture is the
11453                 // current frame/skin the texture is directing us to use (for example
11454                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11455                 // use skin 1 instead)
11456                 texture = surfacelist[i]->texture;
11457                 rsurface.texture = R_GetCurrentTexture(texture);
11458                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11459                 {
11460                         // if this texture is not the kind we want, skip ahead to the next one
11461                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11462                                 ;
11463                         continue;
11464                 }
11465                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11466                 {
11467                         rsurface.lightmaptexture = NULL;
11468                         rsurface.deluxemaptexture = NULL;
11469                         rsurface.uselightmaptexture = false;
11470                         // simply scan ahead until we find a different texture or lightmap state
11471                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11472                                 ;
11473                 }
11474                 else
11475                 {
11476                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11477                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11478                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11479                         // simply scan ahead until we find a different texture or lightmap state
11480                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11481                                 ;
11482                 }
11483                 // render the range of surfaces
11484                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11485         }
11486         R_FrameData_ReturnToMark();
11487 }
11488
11489 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11490 {
11491         CHECKGLERROR
11492         if (depthonly)
11493                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11494         else if (prepass)
11495         {
11496                 if (!rsurface.texture->currentnumlayers)
11497                         return;
11498                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11499                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11500                 else
11501                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11502         }
11503         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11504                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11505         else if (!rsurface.texture->currentnumlayers)
11506                 return;
11507         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11508         {
11509                 // in the deferred case, transparent surfaces were queued during prepass
11510                 if (!r_shadow_usingdeferredprepass)
11511                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11512         }
11513         else
11514         {
11515                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11516                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11517         }
11518         CHECKGLERROR
11519 }
11520
11521 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11522 {
11523         int i, j;
11524         texture_t *texture;
11525         R_FrameData_SetMark();
11526         // break the surface list down into batches by texture and use of lightmapping
11527         for (i = 0;i < numsurfaces;i = j)
11528         {
11529                 j = i + 1;
11530                 // texture is the base texture pointer, rsurface.texture is the
11531                 // current frame/skin the texture is directing us to use (for example
11532                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11533                 // use skin 1 instead)
11534                 texture = surfacelist[i]->texture;
11535                 rsurface.texture = R_GetCurrentTexture(texture);
11536                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11537                 {
11538                         // if this texture is not the kind we want, skip ahead to the next one
11539                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11540                                 ;
11541                         continue;
11542                 }
11543                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11544                 {
11545                         rsurface.lightmaptexture = NULL;
11546                         rsurface.deluxemaptexture = NULL;
11547                         rsurface.uselightmaptexture = false;
11548                         // simply scan ahead until we find a different texture or lightmap state
11549                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11550                                 ;
11551                 }
11552                 else
11553                 {
11554                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11555                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11556                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11557                         // simply scan ahead until we find a different texture or lightmap state
11558                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11559                                 ;
11560                 }
11561                 // render the range of surfaces
11562                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11563         }
11564         R_FrameData_ReturnToMark();
11565 }
11566
11567 float locboxvertex3f[6*4*3] =
11568 {
11569         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11570         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11571         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11572         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11573         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11574         1,0,0, 0,0,0, 0,1,0, 1,1,0
11575 };
11576
11577 unsigned short locboxelements[6*2*3] =
11578 {
11579          0, 1, 2, 0, 2, 3,
11580          4, 5, 6, 4, 6, 7,
11581          8, 9,10, 8,10,11,
11582         12,13,14, 12,14,15,
11583         16,17,18, 16,18,19,
11584         20,21,22, 20,22,23
11585 };
11586
11587 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11588 {
11589         int i, j;
11590         cl_locnode_t *loc = (cl_locnode_t *)ent;
11591         vec3_t mins, size;
11592         float vertex3f[6*4*3];
11593         CHECKGLERROR
11594         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11595         GL_DepthMask(false);
11596         GL_DepthRange(0, 1);
11597         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11598         GL_DepthTest(true);
11599         GL_CullFace(GL_NONE);
11600         R_EntityMatrix(&identitymatrix);
11601
11602 //      R_Mesh_ResetTextureState();
11603
11604         i = surfacelist[0];
11605         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11606                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11607                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11608                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11609
11610         if (VectorCompare(loc->mins, loc->maxs))
11611         {
11612                 VectorSet(size, 2, 2, 2);
11613                 VectorMA(loc->mins, -0.5f, size, mins);
11614         }
11615         else
11616         {
11617                 VectorCopy(loc->mins, mins);
11618                 VectorSubtract(loc->maxs, loc->mins, size);
11619         }
11620
11621         for (i = 0;i < 6*4*3;)
11622                 for (j = 0;j < 3;j++, i++)
11623                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11624
11625         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11626         R_SetupShader_Generic_NoTexture(false, false);
11627         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11628 }
11629
11630 void R_DrawLocs(void)
11631 {
11632         int index;
11633         cl_locnode_t *loc, *nearestloc;
11634         vec3_t center;
11635         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11636         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11637         {
11638                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11639                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11640         }
11641 }
11642
11643 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11644 {
11645         if (decalsystem->decals)
11646                 Mem_Free(decalsystem->decals);
11647         memset(decalsystem, 0, sizeof(*decalsystem));
11648 }
11649
11650 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, unsigned int decalsequence)
11651 {
11652         tridecal_t *decal;
11653         tridecal_t *decals;
11654         int i;
11655
11656         // expand or initialize the system
11657         if (decalsystem->maxdecals <= decalsystem->numdecals)
11658         {
11659                 decalsystem_t old = *decalsystem;
11660                 qboolean useshortelements;
11661                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11662                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11663                 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)));
11664                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11665                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11666                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11667                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11668                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11669                 if (decalsystem->numdecals)
11670                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11671                 if (old.decals)
11672                         Mem_Free(old.decals);
11673                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11674                         decalsystem->element3i[i] = i;
11675                 if (useshortelements)
11676                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11677                                 decalsystem->element3s[i] = i;
11678         }
11679
11680         // grab a decal and search for another free slot for the next one
11681         decals = decalsystem->decals;
11682         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11683         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11684                 ;
11685         decalsystem->freedecal = i;
11686         if (decalsystem->numdecals <= i)
11687                 decalsystem->numdecals = i + 1;
11688
11689         // initialize the decal
11690         decal->lived = 0;
11691         decal->triangleindex = triangleindex;
11692         decal->surfaceindex = surfaceindex;
11693         decal->decalsequence = decalsequence;
11694         decal->color4f[0][0] = c0[0];
11695         decal->color4f[0][1] = c0[1];
11696         decal->color4f[0][2] = c0[2];
11697         decal->color4f[0][3] = 1;
11698         decal->color4f[1][0] = c1[0];
11699         decal->color4f[1][1] = c1[1];
11700         decal->color4f[1][2] = c1[2];
11701         decal->color4f[1][3] = 1;
11702         decal->color4f[2][0] = c2[0];
11703         decal->color4f[2][1] = c2[1];
11704         decal->color4f[2][2] = c2[2];
11705         decal->color4f[2][3] = 1;
11706         decal->vertex3f[0][0] = v0[0];
11707         decal->vertex3f[0][1] = v0[1];
11708         decal->vertex3f[0][2] = v0[2];
11709         decal->vertex3f[1][0] = v1[0];
11710         decal->vertex3f[1][1] = v1[1];
11711         decal->vertex3f[1][2] = v1[2];
11712         decal->vertex3f[2][0] = v2[0];
11713         decal->vertex3f[2][1] = v2[1];
11714         decal->vertex3f[2][2] = v2[2];
11715         decal->texcoord2f[0][0] = t0[0];
11716         decal->texcoord2f[0][1] = t0[1];
11717         decal->texcoord2f[1][0] = t1[0];
11718         decal->texcoord2f[1][1] = t1[1];
11719         decal->texcoord2f[2][0] = t2[0];
11720         decal->texcoord2f[2][1] = t2[1];
11721         TriangleNormal(v0, v1, v2, decal->plane);
11722         VectorNormalize(decal->plane);
11723         decal->plane[3] = DotProduct(v0, decal->plane);
11724 }
11725
11726 extern cvar_t cl_decals_bias;
11727 extern cvar_t cl_decals_models;
11728 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11729 // baseparms, parms, temps
11730 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, unsigned int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11731 {
11732         int cornerindex;
11733         int index;
11734         float v[9][3];
11735         const float *vertex3f;
11736         const float *normal3f;
11737         int numpoints;
11738         float points[2][9][3];
11739         float temp[3];
11740         float tc[9][2];
11741         float f;
11742         float c[9][4];
11743         const int *e;
11744
11745         e = rsurface.modelelement3i + 3*triangleindex;
11746
11747         vertex3f = rsurface.modelvertex3f;
11748         normal3f = rsurface.modelnormal3f;
11749
11750         if (normal3f)
11751         {
11752                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11753                 {
11754                         index = 3*e[cornerindex];
11755                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11756                 }
11757         }
11758         else
11759         {
11760                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11761                 {
11762                         index = 3*e[cornerindex];
11763                         VectorCopy(vertex3f + index, v[cornerindex]);
11764                 }
11765         }
11766
11767         // cull backfaces
11768         //TriangleNormal(v[0], v[1], v[2], normal);
11769         //if (DotProduct(normal, localnormal) < 0.0f)
11770         //      continue;
11771         // clip by each of the box planes formed from the projection matrix
11772         // if anything survives, we emit the decal
11773         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]);
11774         if (numpoints < 3)
11775                 return;
11776         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]);
11777         if (numpoints < 3)
11778                 return;
11779         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]);
11780         if (numpoints < 3)
11781                 return;
11782         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]);
11783         if (numpoints < 3)
11784                 return;
11785         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]);
11786         if (numpoints < 3)
11787                 return;
11788         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]);
11789         if (numpoints < 3)
11790                 return;
11791         // some part of the triangle survived, so we have to accept it...
11792         if (dynamic)
11793         {
11794                 // dynamic always uses the original triangle
11795                 numpoints = 3;
11796                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11797                 {
11798                         index = 3*e[cornerindex];
11799                         VectorCopy(vertex3f + index, v[cornerindex]);
11800                 }
11801         }
11802         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11803         {
11804                 // convert vertex positions to texcoords
11805                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11806                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11807                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11808                 // calculate distance fade from the projection origin
11809                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11810                 f = bound(0.0f, f, 1.0f);
11811                 c[cornerindex][0] = r * f;
11812                 c[cornerindex][1] = g * f;
11813                 c[cornerindex][2] = b * f;
11814                 c[cornerindex][3] = 1.0f;
11815                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11816         }
11817         if (dynamic)
11818                 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);
11819         else
11820                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11821                         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);
11822 }
11823 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, unsigned int decalsequence)
11824 {
11825         matrix4x4_t projection;
11826         decalsystem_t *decalsystem;
11827         qboolean dynamic;
11828         dp_model_t *model;
11829         const msurface_t *surface;
11830         const msurface_t *surfaces;
11831         const int *surfacelist;
11832         const texture_t *texture;
11833         int numtriangles;
11834         int numsurfacelist;
11835         int surfacelistindex;
11836         int surfaceindex;
11837         int triangleindex;
11838         float localorigin[3];
11839         float localnormal[3];
11840         float localmins[3];
11841         float localmaxs[3];
11842         float localsize;
11843         //float normal[3];
11844         float planes[6][4];
11845         float angles[3];
11846         bih_t *bih;
11847         int bih_triangles_count;
11848         int bih_triangles[256];
11849         int bih_surfaces[256];
11850
11851         decalsystem = &ent->decalsystem;
11852         model = ent->model;
11853         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11854         {
11855                 R_DecalSystem_Reset(&ent->decalsystem);
11856                 return;
11857         }
11858
11859         if (!model->brush.data_leafs && !cl_decals_models.integer)
11860         {
11861                 if (decalsystem->model)
11862                         R_DecalSystem_Reset(decalsystem);
11863                 return;
11864         }
11865
11866         if (decalsystem->model != model)
11867                 R_DecalSystem_Reset(decalsystem);
11868         decalsystem->model = model;
11869
11870         RSurf_ActiveModelEntity(ent, true, false, false);
11871
11872         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11873         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11874         VectorNormalize(localnormal);
11875         localsize = worldsize*rsurface.inversematrixscale;
11876         localmins[0] = localorigin[0] - localsize;
11877         localmins[1] = localorigin[1] - localsize;
11878         localmins[2] = localorigin[2] - localsize;
11879         localmaxs[0] = localorigin[0] + localsize;
11880         localmaxs[1] = localorigin[1] + localsize;
11881         localmaxs[2] = localorigin[2] + localsize;
11882
11883         //VectorCopy(localnormal, planes[4]);
11884         //VectorVectors(planes[4], planes[2], planes[0]);
11885         AnglesFromVectors(angles, localnormal, NULL, false);
11886         AngleVectors(angles, planes[0], planes[2], planes[4]);
11887         VectorNegate(planes[0], planes[1]);
11888         VectorNegate(planes[2], planes[3]);
11889         VectorNegate(planes[4], planes[5]);
11890         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11891         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11892         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11893         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11894         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11895         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11896
11897 #if 1
11898 // works
11899 {
11900         matrix4x4_t forwardprojection;
11901         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11902         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11903 }
11904 #else
11905 // broken
11906 {
11907         float projectionvector[4][3];
11908         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11909         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11910         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11911         projectionvector[0][0] = planes[0][0] * ilocalsize;
11912         projectionvector[0][1] = planes[1][0] * ilocalsize;
11913         projectionvector[0][2] = planes[2][0] * ilocalsize;
11914         projectionvector[1][0] = planes[0][1] * ilocalsize;
11915         projectionvector[1][1] = planes[1][1] * ilocalsize;
11916         projectionvector[1][2] = planes[2][1] * ilocalsize;
11917         projectionvector[2][0] = planes[0][2] * ilocalsize;
11918         projectionvector[2][1] = planes[1][2] * ilocalsize;
11919         projectionvector[2][2] = planes[2][2] * ilocalsize;
11920         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11921         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11922         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11923         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11924 }
11925 #endif
11926
11927         dynamic = model->surfmesh.isanimated;
11928         numsurfacelist = model->nummodelsurfaces;
11929         surfacelist = model->sortedmodelsurfaces;
11930         surfaces = model->data_surfaces;
11931
11932         bih = NULL;
11933         bih_triangles_count = -1;
11934         if(!dynamic)
11935         {
11936                 if(model->render_bih.numleafs)
11937                         bih = &model->render_bih;
11938                 else if(model->collision_bih.numleafs)
11939                         bih = &model->collision_bih;
11940         }
11941         if(bih)
11942                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11943         if(bih_triangles_count == 0)
11944                 return;
11945         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11946                 return;
11947         if(bih_triangles_count > 0)
11948         {
11949                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11950                 {
11951                         surfaceindex = bih_surfaces[triangleindex];
11952                         surface = surfaces + surfaceindex;
11953                         texture = surface->texture;
11954                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11955                                 continue;
11956                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11957                                 continue;
11958                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11959                 }
11960         }
11961         else
11962         {
11963                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11964                 {
11965                         surfaceindex = surfacelist[surfacelistindex];
11966                         surface = surfaces + surfaceindex;
11967                         // check cull box first because it rejects more than any other check
11968                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11969                                 continue;
11970                         // skip transparent surfaces
11971                         texture = surface->texture;
11972                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11973                                 continue;
11974                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11975                                 continue;
11976                         numtriangles = surface->num_triangles;
11977                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11978                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11979                 }
11980         }
11981 }
11982
11983 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11984 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, unsigned int decalsequence)
11985 {
11986         int renderentityindex;
11987         float worldmins[3];
11988         float worldmaxs[3];
11989         entity_render_t *ent;
11990
11991         if (!cl_decals_newsystem.integer)
11992                 return;
11993
11994         worldmins[0] = worldorigin[0] - worldsize;
11995         worldmins[1] = worldorigin[1] - worldsize;
11996         worldmins[2] = worldorigin[2] - worldsize;
11997         worldmaxs[0] = worldorigin[0] + worldsize;
11998         worldmaxs[1] = worldorigin[1] + worldsize;
11999         worldmaxs[2] = worldorigin[2] + worldsize;
12000
12001         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12002
12003         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12004         {
12005                 ent = r_refdef.scene.entities[renderentityindex];
12006                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12007                         continue;
12008
12009                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12010         }
12011 }
12012
12013 typedef struct r_decalsystem_splatqueue_s
12014 {
12015         vec3_t worldorigin;
12016         vec3_t worldnormal;
12017         float color[4];
12018         float tcrange[4];
12019         float worldsize;
12020         unsigned int decalsequence;
12021 }
12022 r_decalsystem_splatqueue_t;
12023
12024 int r_decalsystem_numqueued = 0;
12025 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12026
12027 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)
12028 {
12029         r_decalsystem_splatqueue_t *queue;
12030
12031         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12032                 return;
12033
12034         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12035         VectorCopy(worldorigin, queue->worldorigin);
12036         VectorCopy(worldnormal, queue->worldnormal);
12037         Vector4Set(queue->color, r, g, b, a);
12038         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12039         queue->worldsize = worldsize;
12040         queue->decalsequence = cl.decalsequence++;
12041 }
12042
12043 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12044 {
12045         int i;
12046         r_decalsystem_splatqueue_t *queue;
12047
12048         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12049                 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);
12050         r_decalsystem_numqueued = 0;
12051 }
12052
12053 extern cvar_t cl_decals_max;
12054 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12055 {
12056         int i;
12057         decalsystem_t *decalsystem = &ent->decalsystem;
12058         int numdecals;
12059         unsigned int killsequence;
12060         tridecal_t *decal;
12061         float frametime;
12062         float lifetime;
12063
12064         if (!decalsystem->numdecals)
12065                 return;
12066
12067         if (r_showsurfaces.integer)
12068                 return;
12069
12070         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12071         {
12072                 R_DecalSystem_Reset(decalsystem);
12073                 return;
12074         }
12075
12076         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12077         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12078
12079         if (decalsystem->lastupdatetime)
12080                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12081         else
12082                 frametime = 0;
12083         decalsystem->lastupdatetime = r_refdef.scene.time;
12084         numdecals = decalsystem->numdecals;
12085
12086         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12087         {
12088                 if (decal->color4f[0][3])
12089                 {
12090                         decal->lived += frametime;
12091                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12092                         {
12093                                 memset(decal, 0, sizeof(*decal));
12094                                 if (decalsystem->freedecal > i)
12095                                         decalsystem->freedecal = i;
12096                         }
12097                 }
12098         }
12099         decal = decalsystem->decals;
12100         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12101                 numdecals--;
12102
12103         // collapse the array by shuffling the tail decals into the gaps
12104         for (;;)
12105         {
12106                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12107                         decalsystem->freedecal++;
12108                 if (decalsystem->freedecal == numdecals)
12109                         break;
12110                 decal[decalsystem->freedecal] = decal[--numdecals];
12111         }
12112
12113         decalsystem->numdecals = numdecals;
12114
12115         if (numdecals <= 0)
12116         {
12117                 // if there are no decals left, reset decalsystem
12118                 R_DecalSystem_Reset(decalsystem);
12119         }
12120 }
12121
12122 extern skinframe_t *decalskinframe;
12123 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12124 {
12125         int i;
12126         decalsystem_t *decalsystem = &ent->decalsystem;
12127         int numdecals;
12128         tridecal_t *decal;
12129         float faderate;
12130         float alpha;
12131         float *v3f;
12132         float *c4f;
12133         float *t2f;
12134         const int *e;
12135         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12136         int numtris = 0;
12137
12138         numdecals = decalsystem->numdecals;
12139         if (!numdecals)
12140                 return;
12141
12142         if (r_showsurfaces.integer)
12143                 return;
12144
12145         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12146         {
12147                 R_DecalSystem_Reset(decalsystem);
12148                 return;
12149         }
12150
12151         // if the model is static it doesn't matter what value we give for
12152         // wantnormals and wanttangents, so this logic uses only rules applicable
12153         // to a model, knowing that they are meaningless otherwise
12154         if (ent == r_refdef.scene.worldentity)
12155                 RSurf_ActiveWorldEntity();
12156         else
12157                 RSurf_ActiveModelEntity(ent, false, false, false);
12158
12159         decalsystem->lastupdatetime = r_refdef.scene.time;
12160
12161         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12162
12163         // update vertex positions for animated models
12164         v3f = decalsystem->vertex3f;
12165         c4f = decalsystem->color4f;
12166         t2f = decalsystem->texcoord2f;
12167         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12168         {
12169                 if (!decal->color4f[0][3])
12170                         continue;
12171
12172                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12173                         continue;
12174
12175                 // skip backfaces
12176                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12177                         continue;
12178
12179                 // update color values for fading decals
12180                 if (decal->lived >= cl_decals_time.value)
12181                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12182                 else
12183                         alpha = 1.0f;
12184
12185                 c4f[ 0] = decal->color4f[0][0] * alpha;
12186                 c4f[ 1] = decal->color4f[0][1] * alpha;
12187                 c4f[ 2] = decal->color4f[0][2] * alpha;
12188                 c4f[ 3] = 1;
12189                 c4f[ 4] = decal->color4f[1][0] * alpha;
12190                 c4f[ 5] = decal->color4f[1][1] * alpha;
12191                 c4f[ 6] = decal->color4f[1][2] * alpha;
12192                 c4f[ 7] = 1;
12193                 c4f[ 8] = decal->color4f[2][0] * alpha;
12194                 c4f[ 9] = decal->color4f[2][1] * alpha;
12195                 c4f[10] = decal->color4f[2][2] * alpha;
12196                 c4f[11] = 1;
12197
12198                 t2f[0] = decal->texcoord2f[0][0];
12199                 t2f[1] = decal->texcoord2f[0][1];
12200                 t2f[2] = decal->texcoord2f[1][0];
12201                 t2f[3] = decal->texcoord2f[1][1];
12202                 t2f[4] = decal->texcoord2f[2][0];
12203                 t2f[5] = decal->texcoord2f[2][1];
12204
12205                 // update vertex positions for animated models
12206                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12207                 {
12208                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12209                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12210                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12211                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12212                 }
12213                 else
12214                 {
12215                         VectorCopy(decal->vertex3f[0], v3f);
12216                         VectorCopy(decal->vertex3f[1], v3f + 3);
12217                         VectorCopy(decal->vertex3f[2], v3f + 6);
12218                 }
12219
12220                 if (r_refdef.fogenabled)
12221                 {
12222                         alpha = RSurf_FogVertex(v3f);
12223                         VectorScale(c4f, alpha, c4f);
12224                         alpha = RSurf_FogVertex(v3f + 3);
12225                         VectorScale(c4f + 4, alpha, c4f + 4);
12226                         alpha = RSurf_FogVertex(v3f + 6);
12227                         VectorScale(c4f + 8, alpha, c4f + 8);
12228                 }
12229
12230                 v3f += 9;
12231                 c4f += 12;
12232                 t2f += 6;
12233                 numtris++;
12234         }
12235
12236         if (numtris > 0)
12237         {
12238                 r_refdef.stats[r_stat_drawndecals] += numtris;
12239
12240                 // now render the decals all at once
12241                 // (this assumes they all use one particle font texture!)
12242                 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);
12243 //              R_Mesh_ResetTextureState();
12244                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12245                 GL_DepthMask(false);
12246                 GL_DepthRange(0, 1);
12247                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12248                 GL_DepthTest(true);
12249                 GL_CullFace(GL_NONE);
12250                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12251                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12252                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12253         }
12254 }
12255
12256 static void R_DrawModelDecals(void)
12257 {
12258         int i, numdecals;
12259
12260         // fade faster when there are too many decals
12261         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12262         for (i = 0;i < r_refdef.scene.numentities;i++)
12263                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12264
12265         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12266         for (i = 0;i < r_refdef.scene.numentities;i++)
12267                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12268                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12269
12270         R_DecalSystem_ApplySplatEntitiesQueue();
12271
12272         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12273         for (i = 0;i < r_refdef.scene.numentities;i++)
12274                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12275
12276         r_refdef.stats[r_stat_totaldecals] += numdecals;
12277
12278         if (r_showsurfaces.integer)
12279                 return;
12280
12281         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12282
12283         for (i = 0;i < r_refdef.scene.numentities;i++)
12284         {
12285                 if (!r_refdef.viewcache.entityvisible[i])
12286                         continue;
12287                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12288                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12289         }
12290 }
12291
12292 extern cvar_t mod_collision_bih;
12293 static void R_DrawDebugModel(void)
12294 {
12295         entity_render_t *ent = rsurface.entity;
12296         int i, j, flagsmask;
12297         const msurface_t *surface;
12298         dp_model_t *model = ent->model;
12299
12300         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12301                 return;
12302
12303         if (r_showoverdraw.value > 0)
12304         {
12305                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12306                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12307                 R_SetupShader_Generic_NoTexture(false, false);
12308                 GL_DepthTest(false);
12309                 GL_DepthMask(false);
12310                 GL_DepthRange(0, 1);
12311                 GL_BlendFunc(GL_ONE, GL_ONE);
12312                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12313                 {
12314                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12315                                 continue;
12316                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12317                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12318                         {
12319                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12320                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12321                                 if (!rsurface.texture->currentlayers->depthmask)
12322                                         GL_Color(c, 0, 0, 1.0f);
12323                                 else if (ent == r_refdef.scene.worldentity)
12324                                         GL_Color(c, c, c, 1.0f);
12325                                 else
12326                                         GL_Color(0, c, 0, 1.0f);
12327                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12328                                 RSurf_DrawBatch();
12329                         }
12330                 }
12331                 rsurface.texture = NULL;
12332         }
12333
12334         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12335
12336 //      R_Mesh_ResetTextureState();
12337         R_SetupShader_Generic_NoTexture(false, false);
12338         GL_DepthRange(0, 1);
12339         GL_DepthTest(!r_showdisabledepthtest.integer);
12340         GL_DepthMask(false);
12341         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12342
12343         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12344         {
12345                 int triangleindex;
12346                 int bihleafindex;
12347                 qboolean cullbox = false;
12348                 const q3mbrush_t *brush;
12349                 const bih_t *bih = &model->collision_bih;
12350                 const bih_leaf_t *bihleaf;
12351                 float vertex3f[3][3];
12352                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12353                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12354                 {
12355                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12356                                 continue;
12357                         switch (bihleaf->type)
12358                         {
12359                         case BIH_BRUSH:
12360                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12361                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12362                                 {
12363                                         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);
12364                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12365                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12366                                 }
12367                                 break;
12368                         case BIH_COLLISIONTRIANGLE:
12369                                 triangleindex = bihleaf->itemindex;
12370                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12371                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12372                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12373                                 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);
12374                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12375                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12376                                 break;
12377                         case BIH_RENDERTRIANGLE:
12378                                 triangleindex = bihleaf->itemindex;
12379                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12380                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12381                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12382                                 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);
12383                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12384                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12385                                 break;
12386                         }
12387                 }
12388         }
12389
12390         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12391
12392 #ifndef USE_GLES2
12393         if (r_showtris.integer && qglPolygonMode)
12394         {
12395                 if (r_showdisabledepthtest.integer)
12396                 {
12397                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12398                         GL_DepthMask(false);
12399                 }
12400                 else
12401                 {
12402                         GL_BlendFunc(GL_ONE, GL_ZERO);
12403                         GL_DepthMask(true);
12404                 }
12405                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12406                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12407                 {
12408                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12409                                 continue;
12410                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12411                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12412                         {
12413                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12414                                 if (!rsurface.texture->currentlayers->depthmask)
12415                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12416                                 else if (ent == r_refdef.scene.worldentity)
12417                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12418                                 else
12419                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12420                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12421                                 RSurf_DrawBatch();
12422                         }
12423                 }
12424                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12425                 rsurface.texture = NULL;
12426         }
12427
12428         if (r_shownormals.value != 0 && qglBegin)
12429         {
12430                 int l, k;
12431                 vec3_t v;
12432                 if (r_showdisabledepthtest.integer)
12433                 {
12434                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12435                         GL_DepthMask(false);
12436                 }
12437                 else
12438                 {
12439                         GL_BlendFunc(GL_ONE, GL_ZERO);
12440                         GL_DepthMask(true);
12441                 }
12442                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12443                 {
12444                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12445                                 continue;
12446                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12447                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12448                         {
12449                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12450                                 qglBegin(GL_LINES);
12451                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12452                                 {
12453                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12454                                         {
12455                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12456                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12457                                                 qglVertex3f(v[0], v[1], v[2]);
12458                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12459                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12460                                                 qglVertex3f(v[0], v[1], v[2]);
12461                                         }
12462                                 }
12463                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12464                                 {
12465                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12466                                         {
12467                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12468                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12469                                                 qglVertex3f(v[0], v[1], v[2]);
12470                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12471                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12472                                                 qglVertex3f(v[0], v[1], v[2]);
12473                                         }
12474                                 }
12475                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12476                                 {
12477                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12478                                         {
12479                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12480                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12481                                                 qglVertex3f(v[0], v[1], v[2]);
12482                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12483                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12484                                                 qglVertex3f(v[0], v[1], v[2]);
12485                                         }
12486                                 }
12487                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12488                                 {
12489                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12490                                         {
12491                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12492                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12493                                                 qglVertex3f(v[0], v[1], v[2]);
12494                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12495                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12496                                                 qglVertex3f(v[0], v[1], v[2]);
12497                                         }
12498                                 }
12499                                 qglEnd();
12500                                 CHECKGLERROR
12501                         }
12502                 }
12503                 rsurface.texture = NULL;
12504         }
12505 #endif
12506 }
12507
12508 int r_maxsurfacelist = 0;
12509 const msurface_t **r_surfacelist = NULL;
12510 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12511 {
12512         int i, j, endj, flagsmask;
12513         dp_model_t *model = r_refdef.scene.worldmodel;
12514         msurface_t *surfaces;
12515         unsigned char *update;
12516         int numsurfacelist = 0;
12517         if (model == NULL)
12518                 return;
12519
12520         if (r_maxsurfacelist < model->num_surfaces)
12521         {
12522                 r_maxsurfacelist = model->num_surfaces;
12523                 if (r_surfacelist)
12524                         Mem_Free((msurface_t**)r_surfacelist);
12525                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12526         }
12527
12528         RSurf_ActiveWorldEntity();
12529
12530         surfaces = model->data_surfaces;
12531         update = model->brushq1.lightmapupdateflags;
12532
12533         // update light styles on this submodel
12534         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12535         {
12536                 model_brush_lightstyleinfo_t *style;
12537                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12538                 {
12539                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12540                         {
12541                                 int *list = style->surfacelist;
12542                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12543                                 for (j = 0;j < style->numsurfaces;j++)
12544                                         update[list[j]] = true;
12545                         }
12546                 }
12547         }
12548
12549         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12550
12551         if (debug)
12552         {
12553                 R_DrawDebugModel();
12554                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12555                 return;
12556         }
12557
12558         rsurface.lightmaptexture = NULL;
12559         rsurface.deluxemaptexture = NULL;
12560         rsurface.uselightmaptexture = false;
12561         rsurface.texture = NULL;
12562         rsurface.rtlight = NULL;
12563         numsurfacelist = 0;
12564         // add visible surfaces to draw list
12565         for (i = 0;i < model->nummodelsurfaces;i++)
12566         {
12567                 j = model->sortedmodelsurfaces[i];
12568                 if (r_refdef.viewcache.world_surfacevisible[j])
12569                         r_surfacelist[numsurfacelist++] = surfaces + j;
12570         }
12571         // update lightmaps if needed
12572         if (model->brushq1.firstrender)
12573         {
12574                 model->brushq1.firstrender = false;
12575                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12576                         if (update[j])
12577                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12578         }
12579         else if (update)
12580         {
12581                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12582                         if (r_refdef.viewcache.world_surfacevisible[j])
12583                                 if (update[j])
12584                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12585         }
12586         // don't do anything if there were no surfaces
12587         if (!numsurfacelist)
12588         {
12589                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12590                 return;
12591         }
12592         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12593
12594         // add to stats if desired
12595         if (r_speeds.integer && !skysurfaces && !depthonly)
12596         {
12597                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12598                 for (j = 0;j < numsurfacelist;j++)
12599                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12600         }
12601
12602         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12603 }
12604
12605 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12606 {
12607         int i, j, endj, flagsmask;
12608         dp_model_t *model = ent->model;
12609         msurface_t *surfaces;
12610         unsigned char *update;
12611         int numsurfacelist = 0;
12612         if (model == NULL)
12613                 return;
12614
12615         if (r_maxsurfacelist < model->num_surfaces)
12616         {
12617                 r_maxsurfacelist = model->num_surfaces;
12618                 if (r_surfacelist)
12619                         Mem_Free((msurface_t **)r_surfacelist);
12620                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12621         }
12622
12623         // if the model is static it doesn't matter what value we give for
12624         // wantnormals and wanttangents, so this logic uses only rules applicable
12625         // to a model, knowing that they are meaningless otherwise
12626         if (ent == r_refdef.scene.worldentity)
12627                 RSurf_ActiveWorldEntity();
12628         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12629                 RSurf_ActiveModelEntity(ent, false, false, false);
12630         else if (prepass)
12631                 RSurf_ActiveModelEntity(ent, true, true, true);
12632         else if (depthonly)
12633         {
12634                 switch (vid.renderpath)
12635                 {
12636                 case RENDERPATH_GL20:
12637                 case RENDERPATH_D3D9:
12638                 case RENDERPATH_D3D10:
12639                 case RENDERPATH_D3D11:
12640                 case RENDERPATH_SOFT:
12641                 case RENDERPATH_GLES2:
12642                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12643                         break;
12644                 case RENDERPATH_GL11:
12645                 case RENDERPATH_GL13:
12646                 case RENDERPATH_GLES1:
12647                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12648                         break;
12649                 }
12650         }
12651         else
12652         {
12653                 switch (vid.renderpath)
12654                 {
12655                 case RENDERPATH_GL20:
12656                 case RENDERPATH_D3D9:
12657                 case RENDERPATH_D3D10:
12658                 case RENDERPATH_D3D11:
12659                 case RENDERPATH_SOFT:
12660                 case RENDERPATH_GLES2:
12661                         RSurf_ActiveModelEntity(ent, true, true, false);
12662                         break;
12663                 case RENDERPATH_GL11:
12664                 case RENDERPATH_GL13:
12665                 case RENDERPATH_GLES1:
12666                         RSurf_ActiveModelEntity(ent, true, false, false);
12667                         break;
12668                 }
12669         }
12670
12671         surfaces = model->data_surfaces;
12672         update = model->brushq1.lightmapupdateflags;
12673
12674         // update light styles
12675         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12676         {
12677                 model_brush_lightstyleinfo_t *style;
12678                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12679                 {
12680                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12681                         {
12682                                 int *list = style->surfacelist;
12683                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12684                                 for (j = 0;j < style->numsurfaces;j++)
12685                                         update[list[j]] = true;
12686                         }
12687                 }
12688         }
12689
12690         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12691
12692         if (debug)
12693         {
12694                 R_DrawDebugModel();
12695                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12696                 return;
12697         }
12698
12699         rsurface.lightmaptexture = NULL;
12700         rsurface.deluxemaptexture = NULL;
12701         rsurface.uselightmaptexture = false;
12702         rsurface.texture = NULL;
12703         rsurface.rtlight = NULL;
12704         numsurfacelist = 0;
12705         // add visible surfaces to draw list
12706         for (i = 0;i < model->nummodelsurfaces;i++)
12707                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12708         // don't do anything if there were no surfaces
12709         if (!numsurfacelist)
12710         {
12711                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12712                 return;
12713         }
12714         // update lightmaps if needed
12715         if (update)
12716         {
12717                 int updated = 0;
12718                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12719                 {
12720                         if (update[j])
12721                         {
12722                                 updated++;
12723                                 R_BuildLightMap(ent, surfaces + j);
12724                         }
12725                 }
12726         }
12727
12728         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12729
12730         // add to stats if desired
12731         if (r_speeds.integer && !skysurfaces && !depthonly)
12732         {
12733                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12734                 for (j = 0;j < numsurfacelist;j++)
12735                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12736         }
12737
12738         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12739 }
12740
12741 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12742 {
12743         static texture_t texture;
12744         static msurface_t surface;
12745         const msurface_t *surfacelist = &surface;
12746
12747         // fake enough texture and surface state to render this geometry
12748
12749         texture.update_lastrenderframe = -1; // regenerate this texture
12750         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12751         texture.basealpha = 1.0f;
12752         texture.currentskinframe = skinframe;
12753         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12754         texture.offsetmapping = OFFSETMAPPING_OFF;
12755         texture.offsetscale = 1;
12756         texture.specularscalemod = 1;
12757         texture.specularpowermod = 1;
12758         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12759         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12760         // JUST GREP FOR "specularscalemod = 1".
12761
12762         surface.texture = &texture;
12763         surface.num_triangles = numtriangles;
12764         surface.num_firsttriangle = firsttriangle;
12765         surface.num_vertices = numvertices;
12766         surface.num_firstvertex = firstvertex;
12767
12768         // now render it
12769         rsurface.texture = R_GetCurrentTexture(surface.texture);
12770         rsurface.lightmaptexture = NULL;
12771         rsurface.deluxemaptexture = NULL;
12772         rsurface.uselightmaptexture = false;
12773         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12774 }
12775
12776 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)
12777 {
12778         static msurface_t surface;
12779         const msurface_t *surfacelist = &surface;
12780
12781         // fake enough texture and surface state to render this geometry
12782         surface.texture = texture;
12783         surface.num_triangles = numtriangles;
12784         surface.num_firsttriangle = firsttriangle;
12785         surface.num_vertices = numvertices;
12786         surface.num_firstvertex = firstvertex;
12787
12788         // now render it
12789         rsurface.texture = R_GetCurrentTexture(surface.texture);
12790         rsurface.lightmaptexture = NULL;
12791         rsurface.deluxemaptexture = NULL;
12792         rsurface.uselightmaptexture = false;
12793         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12794 }