]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Add entity number to showtex overlay.
[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 #include "cl_collision.h"
32
33 #ifdef SUPPORTD3D
34 #include <d3d9.h>
35 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
36 #endif
37
38 #ifdef WIN32
39 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
44 #ifdef __cplusplus
45 }
46 #endif
47 #endif
48
49 mempool_t *r_main_mempool;
50 rtexturepool_t *r_main_texturepool;
51
52 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53
54 static qboolean r_loadnormalmap;
55 static qboolean r_loadgloss;
56 qboolean r_loadfog;
57 static qboolean r_loaddds;
58 static qboolean r_savedds;
59 static qboolean r_gpuskeletal;
60
61 //
62 // screen size info
63 //
64 r_refdef_t r_refdef;
65
66 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!"};
67 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!"};
68 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
69 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
70 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)"};
71 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
72 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"};
73 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"};
74 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"};
75 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"};
76 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"};
77 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"};
78
79 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
80 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"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
82 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)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
84
85 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"};
86 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
87 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
88 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
89 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
90 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
91 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
92 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"};
93 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"};
94 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"};
95 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
96 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
97 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)"};
98 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
99 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
100 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"};
101 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"};
102 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
103 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"};
104 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"};
105 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"};
106 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
107 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
108 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
109 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
110 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
111 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
112 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
113 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
114 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)"};
115 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)"};
116 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
117 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
118 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
119 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
120 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
121 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
122
123 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
124 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
125 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
126
127 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
128 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
129 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
130 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."};
131 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
132 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
133 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
134 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."};
135 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
136 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
137 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
138 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."};
139 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
140 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"};
141 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"};
142 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
143 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
144 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
145 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
146 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
147 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"};
148 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
149 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
150 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
151 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
152 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
153
154 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
155 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
156 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
157 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
158 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
159 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
160 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
161 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
162
163 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)"};
164 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"};
165
166 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
167 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
168 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
169
170 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"};
171 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"};
172 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"};
173 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
174 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
175 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"};
176 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)"};
177 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)"};
178 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
179
180 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
181 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)"};
182 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
183 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)"};
184 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
185 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)"};
186 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)"};
187 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
188 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"};
189 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."};
190 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
191 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)"};
192 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)"};
193 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)"};
194 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)"};
195 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)"};
196 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)"};
197 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)"};
198 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)"};
199
200 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)"};
201 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)"};
202 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
203 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"};
204 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
205 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
206 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
207 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"};
208 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"};
209 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)"};
210
211 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
212 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
213 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
214 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
215
216 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
217 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
218
219 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
220 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
221 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
222 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
223 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
224 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
225
226 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
227 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
228 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
229 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
230 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
231 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
232 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
233 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
234 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
235 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
236
237 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"};
238
239 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"};
240
241 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
242
243 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
244
245 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)"};
246 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)"};
247 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
248 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
249
250 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
251 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"};
252
253 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."};
254
255 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)"};
256 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
257 {
258         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
259         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
260         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
261         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
262 };
263
264 extern cvar_t v_glslgamma;
265 extern cvar_t v_glslgamma_2d;
266
267 extern qboolean v_flipped_state;
268
269 r_framebufferstate_t r_fb;
270
271 /// shadow volume bsp struct with automatically growing nodes buffer
272 svbsp_t r_svbsp;
273
274 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
275
276 rtexture_t *r_texture_blanknormalmap;
277 rtexture_t *r_texture_white;
278 rtexture_t *r_texture_grey128;
279 rtexture_t *r_texture_black;
280 rtexture_t *r_texture_notexture;
281 rtexture_t *r_texture_whitecube;
282 rtexture_t *r_texture_normalizationcube;
283 rtexture_t *r_texture_fogattenuation;
284 rtexture_t *r_texture_fogheighttexture;
285 rtexture_t *r_texture_gammaramps;
286 unsigned int r_texture_gammaramps_serial;
287 //rtexture_t *r_texture_fogintensity;
288 rtexture_t *r_texture_reflectcube;
289
290 // TODO: hash lookups?
291 typedef struct cubemapinfo_s
292 {
293         char basename[64];
294         rtexture_t *texture;
295 }
296 cubemapinfo_t;
297
298 int r_texture_numcubemaps;
299 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
300
301 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
302 unsigned int r_numqueries;
303 unsigned int r_maxqueries;
304
305 typedef struct r_qwskincache_s
306 {
307         char name[MAX_QPATH];
308         skinframe_t *skinframe;
309 }
310 r_qwskincache_t;
311
312 static r_qwskincache_t *r_qwskincache;
313 static int r_qwskincache_size;
314
315 /// vertex coordinates for a quad that covers the screen exactly
316 extern const float r_screenvertex3f[12];
317 extern const float r_d3dscreenvertex3f[12];
318 const float r_screenvertex3f[12] =
319 {
320         0, 0, 0,
321         1, 0, 0,
322         1, 1, 0,
323         0, 1, 0
324 };
325 const float r_d3dscreenvertex3f[12] =
326 {
327         0, 1, 0,
328         1, 1, 0,
329         1, 0, 0,
330         0, 0, 0
331 };
332
333 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
334 {
335         int i;
336         for (i = 0;i < verts;i++)
337         {
338                 out[0] = in[0] * r;
339                 out[1] = in[1] * g;
340                 out[2] = in[2] * b;
341                 out[3] = in[3];
342                 in += 4;
343                 out += 4;
344         }
345 }
346
347 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
348 {
349         int i;
350         for (i = 0;i < verts;i++)
351         {
352                 out[0] = r;
353                 out[1] = g;
354                 out[2] = b;
355                 out[3] = a;
356                 out += 4;
357         }
358 }
359
360 // FIXME: move this to client?
361 void FOG_clear(void)
362 {
363         if (gamemode == GAME_NEHAHRA)
364         {
365                 Cvar_Set("gl_fogenable", "0");
366                 Cvar_Set("gl_fogdensity", "0.2");
367                 Cvar_Set("gl_fogred", "0.3");
368                 Cvar_Set("gl_foggreen", "0.3");
369                 Cvar_Set("gl_fogblue", "0.3");
370         }
371         r_refdef.fog_density = 0;
372         r_refdef.fog_red = 0;
373         r_refdef.fog_green = 0;
374         r_refdef.fog_blue = 0;
375         r_refdef.fog_alpha = 1;
376         r_refdef.fog_start = 0;
377         r_refdef.fog_end = 16384;
378         r_refdef.fog_height = 1<<30;
379         r_refdef.fog_fadedepth = 128;
380         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
381 }
382
383 static void R_BuildBlankTextures(void)
384 {
385         unsigned char data[4];
386         data[2] = 128; // normal X
387         data[1] = 128; // normal Y
388         data[0] = 255; // normal Z
389         data[3] = 255; // height
390         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391         data[0] = 255;
392         data[1] = 255;
393         data[2] = 255;
394         data[3] = 255;
395         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396         data[0] = 128;
397         data[1] = 128;
398         data[2] = 128;
399         data[3] = 255;
400         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
401         data[0] = 0;
402         data[1] = 0;
403         data[2] = 0;
404         data[3] = 255;
405         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
406 }
407
408 static void R_BuildNoTexture(void)
409 {
410         int x, y;
411         unsigned char pix[16][16][4];
412         // this makes a light grey/dark grey checkerboard texture
413         for (y = 0;y < 16;y++)
414         {
415                 for (x = 0;x < 16;x++)
416                 {
417                         if ((y < 8) ^ (x < 8))
418                         {
419                                 pix[y][x][0] = 128;
420                                 pix[y][x][1] = 128;
421                                 pix[y][x][2] = 128;
422                                 pix[y][x][3] = 255;
423                         }
424                         else
425                         {
426                                 pix[y][x][0] = 64;
427                                 pix[y][x][1] = 64;
428                                 pix[y][x][2] = 64;
429                                 pix[y][x][3] = 255;
430                         }
431                 }
432         }
433         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
434 }
435
436 static void R_BuildWhiteCube(void)
437 {
438         unsigned char data[6*1*1*4];
439         memset(data, 255, sizeof(data));
440         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
441 }
442
443 static void R_BuildNormalizationCube(void)
444 {
445         int x, y, side;
446         vec3_t v;
447         vec_t s, t, intensity;
448 #define NORMSIZE 64
449         unsigned char *data;
450         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
451         for (side = 0;side < 6;side++)
452         {
453                 for (y = 0;y < NORMSIZE;y++)
454                 {
455                         for (x = 0;x < NORMSIZE;x++)
456                         {
457                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
458                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
459                                 switch(side)
460                                 {
461                                 default:
462                                 case 0:
463                                         v[0] = 1;
464                                         v[1] = -t;
465                                         v[2] = -s;
466                                         break;
467                                 case 1:
468                                         v[0] = -1;
469                                         v[1] = -t;
470                                         v[2] = s;
471                                         break;
472                                 case 2:
473                                         v[0] = s;
474                                         v[1] = 1;
475                                         v[2] = t;
476                                         break;
477                                 case 3:
478                                         v[0] = s;
479                                         v[1] = -1;
480                                         v[2] = -t;
481                                         break;
482                                 case 4:
483                                         v[0] = s;
484                                         v[1] = -t;
485                                         v[2] = 1;
486                                         break;
487                                 case 5:
488                                         v[0] = -s;
489                                         v[1] = -t;
490                                         v[2] = -1;
491                                         break;
492                                 }
493                                 intensity = 127.0f / sqrt(DotProduct(v, v));
494                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
495                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
496                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
497                                 data[((side*64+y)*64+x)*4+3] = 255;
498                         }
499                 }
500         }
501         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
502         Mem_Free(data);
503 }
504
505 static void R_BuildFogTexture(void)
506 {
507         int x, b;
508 #define FOGWIDTH 256
509         unsigned char data1[FOGWIDTH][4];
510         //unsigned char data2[FOGWIDTH][4];
511         double d, r, alpha;
512
513         r_refdef.fogmasktable_start = r_refdef.fog_start;
514         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
515         r_refdef.fogmasktable_range = r_refdef.fogrange;
516         r_refdef.fogmasktable_density = r_refdef.fog_density;
517
518         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
519         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
520         {
521                 d = (x * r - r_refdef.fogmasktable_start);
522                 if(developer_extra.integer)
523                         Con_DPrintf("%f ", d);
524                 d = max(0, d);
525                 if (r_fog_exp2.integer)
526                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
527                 else
528                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
529                 if(developer_extra.integer)
530                         Con_DPrintf(" : %f ", alpha);
531                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
532                 if(developer_extra.integer)
533                         Con_DPrintf(" = %f\n", alpha);
534                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
535         }
536
537         for (x = 0;x < FOGWIDTH;x++)
538         {
539                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
540                 data1[x][0] = b;
541                 data1[x][1] = b;
542                 data1[x][2] = b;
543                 data1[x][3] = 255;
544                 //data2[x][0] = 255 - b;
545                 //data2[x][1] = 255 - b;
546                 //data2[x][2] = 255 - b;
547                 //data2[x][3] = 255;
548         }
549         if (r_texture_fogattenuation)
550         {
551                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
552                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
553         }
554         else
555         {
556                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
557                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
558         }
559 }
560
561 static void R_BuildFogHeightTexture(void)
562 {
563         unsigned char *inpixels;
564         int size;
565         int x;
566         int y;
567         int j;
568         float c[4];
569         float f;
570         inpixels = NULL;
571         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
572         if (r_refdef.fogheighttexturename[0])
573                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
574         if (!inpixels)
575         {
576                 r_refdef.fog_height_tablesize = 0;
577                 if (r_texture_fogheighttexture)
578                         R_FreeTexture(r_texture_fogheighttexture);
579                 r_texture_fogheighttexture = NULL;
580                 if (r_refdef.fog_height_table2d)
581                         Mem_Free(r_refdef.fog_height_table2d);
582                 r_refdef.fog_height_table2d = NULL;
583                 if (r_refdef.fog_height_table1d)
584                         Mem_Free(r_refdef.fog_height_table1d);
585                 r_refdef.fog_height_table1d = NULL;
586                 return;
587         }
588         size = image_width;
589         r_refdef.fog_height_tablesize = size;
590         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
591         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
592         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
593         Mem_Free(inpixels);
594         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
595         // average fog color table accounting for every fog layer between a point
596         // and the camera.  (Note: attenuation is handled separately!)
597         for (y = 0;y < size;y++)
598         {
599                 for (x = 0;x < size;x++)
600                 {
601                         Vector4Clear(c);
602                         f = 0;
603                         if (x < y)
604                         {
605                                 for (j = x;j <= y;j++)
606                                 {
607                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
608                                         f++;
609                                 }
610                         }
611                         else
612                         {
613                                 for (j = x;j >= y;j--)
614                                 {
615                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
616                                         f++;
617                                 }
618                         }
619                         f = 1.0f / f;
620                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
621                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
622                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
623                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
624                 }
625         }
626         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
627 }
628
629 //=======================================================================================================================================================
630
631 static const char *builtinshaderstrings[] =
632 {
633 #include "shader_glsl.h"
634 0
635 };
636
637 const char *builtinhlslshaderstrings[] =
638 {
639 #include "shader_hlsl.h"
640 0
641 };
642
643 //=======================================================================================================================================================
644
645 typedef struct shaderpermutationinfo_s
646 {
647         const char *pretext;
648         const char *name;
649 }
650 shaderpermutationinfo_t;
651
652 typedef struct shadermodeinfo_s
653 {
654         const char *sourcebasename;
655         const char *extension;
656         const char **builtinshaderstrings;
657         const char *pretext;
658         const char *name;
659         char *filename;
660         char *builtinstring;
661         int builtincrc;
662 }
663 shadermodeinfo_t;
664
665 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
666 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
667 {
668         {"#define USEDIFFUSE\n", " diffuse"},
669         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
670         {"#define USEVIEWTINT\n", " viewtint"},
671         {"#define USECOLORMAPPING\n", " colormapping"},
672         {"#define USESATURATION\n", " saturation"},
673         {"#define USEFOGINSIDE\n", " foginside"},
674         {"#define USEFOGOUTSIDE\n", " fogoutside"},
675         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
676         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
677         {"#define USEGAMMARAMPS\n", " gammaramps"},
678         {"#define USECUBEFILTER\n", " cubefilter"},
679         {"#define USEGLOW\n", " glow"},
680         {"#define USEBLOOM\n", " bloom"},
681         {"#define USESPECULAR\n", " specular"},
682         {"#define USEPOSTPROCESSING\n", " postprocessing"},
683         {"#define USEREFLECTION\n", " reflection"},
684         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
685         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
686         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
687         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
688         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
689         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
690         {"#define USEALPHAKILL\n", " alphakill"},
691         {"#define USEREFLECTCUBE\n", " reflectcube"},
692         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
693         {"#define USEBOUNCEGRID\n", " bouncegrid"},
694         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
695         {"#define USETRIPPY\n", " trippy"},
696         {"#define USEDEPTHRGB\n", " depthrgb"},
697         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
698         {"#define USESKELETAL\n", " skeletal"},
699         {"#define USEOCCLUDE\n", " occlude"}
700 };
701
702 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
703 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
704 {
705         // SHADERLANGUAGE_GLSL
706         {
707                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
708                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
709                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
710                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
711                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
712                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
723                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
724         },
725         // SHADERLANGUAGE_HLSL
726         {
727                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
728                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
729                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
730                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
731                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
732                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
743                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
744         },
745 };
746
747 struct r_glsl_permutation_s;
748 typedef struct r_glsl_permutation_s
749 {
750         /// hash lookup data
751         struct r_glsl_permutation_s *hashnext;
752         unsigned int mode;
753         unsigned int permutation;
754
755         /// indicates if we have tried compiling this permutation already
756         qboolean compiled;
757         /// 0 if compilation failed
758         int program;
759         // texture units assigned to each detected uniform
760         int tex_Texture_First;
761         int tex_Texture_Second;
762         int tex_Texture_GammaRamps;
763         int tex_Texture_Normal;
764         int tex_Texture_Color;
765         int tex_Texture_Gloss;
766         int tex_Texture_Glow;
767         int tex_Texture_SecondaryNormal;
768         int tex_Texture_SecondaryColor;
769         int tex_Texture_SecondaryGloss;
770         int tex_Texture_SecondaryGlow;
771         int tex_Texture_Pants;
772         int tex_Texture_Shirt;
773         int tex_Texture_FogHeightTexture;
774         int tex_Texture_FogMask;
775         int tex_Texture_Lightmap;
776         int tex_Texture_Deluxemap;
777         int tex_Texture_Attenuation;
778         int tex_Texture_Cube;
779         int tex_Texture_Refraction;
780         int tex_Texture_Reflection;
781         int tex_Texture_ShadowMap2D;
782         int tex_Texture_CubeProjection;
783         int tex_Texture_ScreenNormalMap;
784         int tex_Texture_ScreenDiffuse;
785         int tex_Texture_ScreenSpecular;
786         int tex_Texture_ReflectMask;
787         int tex_Texture_ReflectCube;
788         int tex_Texture_BounceGrid;
789         /// locations of detected uniforms in program object, or -1 if not found
790         int loc_Texture_First;
791         int loc_Texture_Second;
792         int loc_Texture_GammaRamps;
793         int loc_Texture_Normal;
794         int loc_Texture_Color;
795         int loc_Texture_Gloss;
796         int loc_Texture_Glow;
797         int loc_Texture_SecondaryNormal;
798         int loc_Texture_SecondaryColor;
799         int loc_Texture_SecondaryGloss;
800         int loc_Texture_SecondaryGlow;
801         int loc_Texture_Pants;
802         int loc_Texture_Shirt;
803         int loc_Texture_FogHeightTexture;
804         int loc_Texture_FogMask;
805         int loc_Texture_Lightmap;
806         int loc_Texture_Deluxemap;
807         int loc_Texture_Attenuation;
808         int loc_Texture_Cube;
809         int loc_Texture_Refraction;
810         int loc_Texture_Reflection;
811         int loc_Texture_ShadowMap2D;
812         int loc_Texture_CubeProjection;
813         int loc_Texture_ScreenNormalMap;
814         int loc_Texture_ScreenDiffuse;
815         int loc_Texture_ScreenSpecular;
816         int loc_Texture_ReflectMask;
817         int loc_Texture_ReflectCube;
818         int loc_Texture_BounceGrid;
819         int loc_Alpha;
820         int loc_BloomBlur_Parameters;
821         int loc_ClientTime;
822         int loc_Color_Ambient;
823         int loc_Color_Diffuse;
824         int loc_Color_Specular;
825         int loc_Color_Glow;
826         int loc_Color_Pants;
827         int loc_Color_Shirt;
828         int loc_DeferredColor_Ambient;
829         int loc_DeferredColor_Diffuse;
830         int loc_DeferredColor_Specular;
831         int loc_DeferredMod_Diffuse;
832         int loc_DeferredMod_Specular;
833         int loc_DistortScaleRefractReflect;
834         int loc_EyePosition;
835         int loc_FogColor;
836         int loc_FogHeightFade;
837         int loc_FogPlane;
838         int loc_FogPlaneViewDist;
839         int loc_FogRangeRecip;
840         int loc_LightColor;
841         int loc_LightDir;
842         int loc_LightPosition;
843         int loc_OffsetMapping_ScaleSteps;
844         int loc_OffsetMapping_LodDistance;
845         int loc_OffsetMapping_Bias;
846         int loc_PixelSize;
847         int loc_ReflectColor;
848         int loc_ReflectFactor;
849         int loc_ReflectOffset;
850         int loc_RefractColor;
851         int loc_Saturation;
852         int loc_ScreenCenterRefractReflect;
853         int loc_ScreenScaleRefractReflect;
854         int loc_ScreenToDepth;
855         int loc_ShadowMap_Parameters;
856         int loc_ShadowMap_TextureScale;
857         int loc_SpecularPower;
858         int loc_Skeletal_Transform12;
859         int loc_UserVec1;
860         int loc_UserVec2;
861         int loc_UserVec3;
862         int loc_UserVec4;
863         int loc_ViewTintColor;
864         int loc_ViewToLight;
865         int loc_ModelToLight;
866         int loc_TexMatrix;
867         int loc_BackgroundTexMatrix;
868         int loc_ModelViewProjectionMatrix;
869         int loc_ModelViewMatrix;
870         int loc_PixelToScreenTexCoord;
871         int loc_ModelToReflectCube;
872         int loc_ShadowMapMatrix;
873         int loc_BloomColorSubtract;
874         int loc_NormalmapScrollBlend;
875         int loc_BounceGridMatrix;
876         int loc_BounceGridIntensity;
877         /// uniform block bindings
878         int ubibind_Skeletal_Transform12_UniformBlock;
879         /// uniform block indices
880         int ubiloc_Skeletal_Transform12_UniformBlock;
881 }
882 r_glsl_permutation_t;
883
884 #define SHADERPERMUTATION_HASHSIZE 256
885
886
887 // non-degradable "lightweight" shader parameters to keep the permutations simpler
888 // these can NOT degrade! only use for simple stuff
889 enum
890 {
891         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
892         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
893         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
894         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
895         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
896         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
897         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
898         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
899         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
900         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
901         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
902         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
903         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
904         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
905 };
906 #define SHADERSTATICPARMS_COUNT 14
907
908 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
909 static int shaderstaticparms_count = 0;
910
911 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
912 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
913
914 extern qboolean r_shadow_shadowmapsampler;
915 extern int r_shadow_shadowmappcf;
916 qboolean R_CompileShader_CheckStaticParms(void)
917 {
918         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
919         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
920         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
921
922         // detect all
923         if (r_glsl_saturation_redcompensate.integer)
924                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
925         if (r_glsl_vertextextureblend_usebothalphas.integer)
926                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
927         if (r_shadow_glossexact.integer)
928                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
929         if (r_glsl_postprocess.integer)
930         {
931                 if (r_glsl_postprocess_uservec1_enable.integer)
932                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
933                 if (r_glsl_postprocess_uservec2_enable.integer)
934                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
935                 if (r_glsl_postprocess_uservec3_enable.integer)
936                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
937                 if (r_glsl_postprocess_uservec4_enable.integer)
938                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
939         }
940         if (r_fxaa.integer)
941                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
942         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
943                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
944
945         if (r_shadow_shadowmapsampler)
946                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
947         if (r_shadow_shadowmappcf > 1)
948                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
949         else if (r_shadow_shadowmappcf)
950                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
951         if (r_celshading.integer)
952                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
953         if (r_celoutlines.integer)
954                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
955
956         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
957 }
958
959 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
960         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
961                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
962         else \
963                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
964 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
965 {
966         shaderstaticparms_count = 0;
967
968         // emit all
969         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
972         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
973         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
982         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
983 }
984
985 /// information about each possible shader permutation
986 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
987 /// currently selected permutation
988 r_glsl_permutation_t *r_glsl_permutation;
989 /// storage for permutations linked in the hash table
990 memexpandablearray_t r_glsl_permutationarray;
991
992 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
993 {
994         //unsigned int hashdepth = 0;
995         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
996         r_glsl_permutation_t *p;
997         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
998         {
999                 if (p->mode == mode && p->permutation == permutation)
1000                 {
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                 //hashdepth++;
1006         }
1007         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1008         p->mode = mode;
1009         p->permutation = permutation;
1010         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1011         r_glsl_permutationhash[mode][hashindex] = p;
1012         //if (hashdepth > 10)
1013         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1014         return p;
1015 }
1016
1017 static char *R_ShaderStrCat(const char **strings)
1018 {
1019         char *string, *s;
1020         const char **p = strings;
1021         const char *t;
1022         size_t len = 0;
1023         for (p = strings;(t = *p);p++)
1024                 len += strlen(t);
1025         len++;
1026         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1027         len = 0;
1028         for (p = strings;(t = *p);p++)
1029         {
1030                 len = strlen(t);
1031                 memcpy(s, t, len);
1032                 s += len;
1033         }
1034         *s = 0;
1035         return string;
1036 }
1037
1038 static char *R_ShaderStrCat(const char **strings);
1039 static void R_InitShaderModeInfo(void)
1040 {
1041         int i, language;
1042         shadermodeinfo_t *modeinfo;
1043         // we have a bunch of things to compute that weren't calculated at engine compile time - all filenames should have a crc of the builtin strings to prevent accidental overrides (any customization must be updated to match engine)
1044         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1045         {
1046                 for (i = 0; i < SHADERMODE_COUNT; i++)
1047                 {
1048                         char filename[MAX_QPATH];
1049                         modeinfo = &shadermodeinfo[language][i];
1050                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1051                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1052                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1053                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1054                 }
1055         }
1056 }
1057
1058 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1059 {
1060         char *shaderstring;
1061         // if the mode has no filename we have to return the builtin string
1062         if (builtinonly || !modeinfo->filename)
1063                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1064         // note that FS_LoadFile appends a 0 byte to make it a valid string
1065         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1066         if (shaderstring)
1067         {
1068                 if (printfromdisknotice)
1069                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1070                 return shaderstring;
1071         }
1072         // fall back to builtinstring
1073         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1074 }
1075
1076 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1077 {
1078         int i;
1079         int ubibind;
1080         int sampler;
1081         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1082         char *sourcestring;
1083         char permutationname[256];
1084         int vertstrings_count = 0;
1085         int geomstrings_count = 0;
1086         int fragstrings_count = 0;
1087         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1088         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1089         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1090
1091         if (p->compiled)
1092                 return;
1093         p->compiled = true;
1094         p->program = 0;
1095
1096         permutationname[0] = 0;
1097         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1098
1099         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1100
1101         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1102         if(vid.support.glshaderversion >= 140)
1103         {
1104                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1105                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1106                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1107                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1108                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1109                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1110         }
1111         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1112         else if(vid.support.glshaderversion >= 130)
1113         {
1114                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1115                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1116                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1117                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1118                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1119                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1120         }
1121         // if we can do #version 120, we should (this adds the invariant keyword)
1122         else if(vid.support.glshaderversion >= 120)
1123         {
1124                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1125                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1126                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1127                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1128                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1129                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1130         }
1131         // GLES also adds several things from GLSL120
1132         switch(vid.renderpath)
1133         {
1134         case RENDERPATH_GLES2:
1135                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1136                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1137                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1138                 break;
1139         default:
1140                 break;
1141         }
1142
1143         // the first pretext is which type of shader to compile as
1144         // (later these will all be bound together as a program object)
1145         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1146         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1147         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1148
1149         // the second pretext is the mode (for example a light source)
1150         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1151         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1152         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1153         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1154
1155         // now add all the permutation pretexts
1156         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1157         {
1158                 if (permutation & (1<<i))
1159                 {
1160                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1161                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1162                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1163                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1164                 }
1165                 else
1166                 {
1167                         // keep line numbers correct
1168                         vertstrings_list[vertstrings_count++] = "\n";
1169                         geomstrings_list[geomstrings_count++] = "\n";
1170                         fragstrings_list[fragstrings_count++] = "\n";
1171                 }
1172         }
1173
1174         // add static parms
1175         R_CompileShader_AddStaticParms(mode, permutation);
1176         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1177         vertstrings_count += shaderstaticparms_count;
1178         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1179         geomstrings_count += shaderstaticparms_count;
1180         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1181         fragstrings_count += shaderstaticparms_count;
1182
1183         // now append the shader text itself
1184         vertstrings_list[vertstrings_count++] = sourcestring;
1185         geomstrings_list[geomstrings_count++] = sourcestring;
1186         fragstrings_list[fragstrings_count++] = sourcestring;
1187
1188         // compile the shader program
1189         if (vertstrings_count + geomstrings_count + fragstrings_count)
1190                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1191         if (p->program)
1192         {
1193                 CHECKGLERROR
1194                 qglUseProgram(p->program);CHECKGLERROR
1195                 // look up all the uniform variable names we care about, so we don't
1196                 // have to look them up every time we set them
1197
1198 #if 0
1199                 // debugging aid
1200                 {
1201                         GLint activeuniformindex = 0;
1202                         GLint numactiveuniforms = 0;
1203                         char uniformname[128];
1204                         GLsizei uniformnamelength = 0;
1205                         GLint uniformsize = 0;
1206                         GLenum uniformtype = 0;
1207                         memset(uniformname, 0, sizeof(uniformname));
1208                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1209                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1210                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1211                         {
1212                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1213                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1214                         }
1215                 }
1216 #endif
1217
1218                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1219                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1220                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1221                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1222                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1223                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1224                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1225                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1226                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1227                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1228                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1229                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1230                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1231                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1232                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1233                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1234                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1235                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1236                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1237                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1238                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1239                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1240                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1241                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1242                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1243                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1244                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1245                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1246                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1247                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1248                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1249                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1250                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1251                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1252                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1253                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1254                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1255                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1256                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1257                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1258                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1259                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1260                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1261                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1262                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1263                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1264                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1265                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1266                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1267                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1268                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1269                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1270                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1271                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1272                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1273                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1274                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1275                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1276                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1277                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1278                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1279                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1280                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1281                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1282                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1283                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1284                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1285                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1286                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1287                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1288                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1289                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1290                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1291                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1292                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1293                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1294                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1295                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1296                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1297                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1298                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1299                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1300                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1301                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1302                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1303                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1304                 // initialize the samplers to refer to the texture units we use
1305                 p->tex_Texture_First = -1;
1306                 p->tex_Texture_Second = -1;
1307                 p->tex_Texture_GammaRamps = -1;
1308                 p->tex_Texture_Normal = -1;
1309                 p->tex_Texture_Color = -1;
1310                 p->tex_Texture_Gloss = -1;
1311                 p->tex_Texture_Glow = -1;
1312                 p->tex_Texture_SecondaryNormal = -1;
1313                 p->tex_Texture_SecondaryColor = -1;
1314                 p->tex_Texture_SecondaryGloss = -1;
1315                 p->tex_Texture_SecondaryGlow = -1;
1316                 p->tex_Texture_Pants = -1;
1317                 p->tex_Texture_Shirt = -1;
1318                 p->tex_Texture_FogHeightTexture = -1;
1319                 p->tex_Texture_FogMask = -1;
1320                 p->tex_Texture_Lightmap = -1;
1321                 p->tex_Texture_Deluxemap = -1;
1322                 p->tex_Texture_Attenuation = -1;
1323                 p->tex_Texture_Cube = -1;
1324                 p->tex_Texture_Refraction = -1;
1325                 p->tex_Texture_Reflection = -1;
1326                 p->tex_Texture_ShadowMap2D = -1;
1327                 p->tex_Texture_CubeProjection = -1;
1328                 p->tex_Texture_ScreenNormalMap = -1;
1329                 p->tex_Texture_ScreenDiffuse = -1;
1330                 p->tex_Texture_ScreenSpecular = -1;
1331                 p->tex_Texture_ReflectMask = -1;
1332                 p->tex_Texture_ReflectCube = -1;
1333                 p->tex_Texture_BounceGrid = -1;
1334                 // bind the texture samplers in use
1335                 sampler = 0;
1336                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1337                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1338                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1339                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1340                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1341                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1342                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1343                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1344                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1345                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1346                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1347                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1348                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1349                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1350                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1351                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1352                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1353                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1354                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1355                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1356                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1357                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1358                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1359                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1360                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1361                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1362                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1363                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1364                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1365                 // get the uniform block indices so we can bind them
1366 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1367                 if (vid.support.arb_uniform_buffer_object)
1368                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1369                 else
1370 #endif
1371                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1372                 // clear the uniform block bindings
1373                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1374                 // bind the uniform blocks in use
1375                 ubibind = 0;
1376 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1377                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1378 #endif
1379                 // we're done compiling and setting up the shader, at least until it is used
1380                 CHECKGLERROR
1381                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1382         }
1383         else
1384                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1385
1386         // free the strings
1387         if (sourcestring)
1388                 Mem_Free(sourcestring);
1389 }
1390
1391 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1392 {
1393         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1394         if (r_glsl_permutation != perm)
1395         {
1396                 r_glsl_permutation = perm;
1397                 if (!r_glsl_permutation->program)
1398                 {
1399                         if (!r_glsl_permutation->compiled)
1400                         {
1401                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1402                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1403                         }
1404                         if (!r_glsl_permutation->program)
1405                         {
1406                                 // remove features until we find a valid permutation
1407                                 int i;
1408                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1409                                 {
1410                                         // reduce i more quickly whenever it would not remove any bits
1411                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1412                                         if (!(permutation & j))
1413                                                 continue;
1414                                         permutation -= j;
1415                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1416                                         if (!r_glsl_permutation->compiled)
1417                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1418                                         if (r_glsl_permutation->program)
1419                                                 break;
1420                                 }
1421                                 if (i >= SHADERPERMUTATION_COUNT)
1422                                 {
1423                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1424                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1425                                         qglUseProgram(0);CHECKGLERROR
1426                                         return; // no bit left to clear, entire mode is broken
1427                                 }
1428                         }
1429                 }
1430                 CHECKGLERROR
1431                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1432         }
1433         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1434         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1435         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1436         CHECKGLERROR
1437 }
1438
1439 #ifdef SUPPORTD3D
1440
1441 #ifdef SUPPORTD3D
1442 #include <d3d9.h>
1443 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1444 extern D3DCAPS9 vid_d3d9caps;
1445 #endif
1446
1447 struct r_hlsl_permutation_s;
1448 typedef struct r_hlsl_permutation_s
1449 {
1450         /// hash lookup data
1451         struct r_hlsl_permutation_s *hashnext;
1452         unsigned int mode;
1453         unsigned int permutation;
1454
1455         /// indicates if we have tried compiling this permutation already
1456         qboolean compiled;
1457         /// NULL if compilation failed
1458         IDirect3DVertexShader9 *vertexshader;
1459         IDirect3DPixelShader9 *pixelshader;
1460 }
1461 r_hlsl_permutation_t;
1462
1463 typedef enum D3DVSREGISTER_e
1464 {
1465         D3DVSREGISTER_TexMatrix = 0, // float4x4
1466         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1467         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1468         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1469         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1470         D3DVSREGISTER_ModelToLight = 20, // float4x4
1471         D3DVSREGISTER_EyePosition = 24,
1472         D3DVSREGISTER_FogPlane = 25,
1473         D3DVSREGISTER_LightDir = 26,
1474         D3DVSREGISTER_LightPosition = 27,
1475 }
1476 D3DVSREGISTER_t;
1477
1478 typedef enum D3DPSREGISTER_e
1479 {
1480         D3DPSREGISTER_Alpha = 0,
1481         D3DPSREGISTER_BloomBlur_Parameters = 1,
1482         D3DPSREGISTER_ClientTime = 2,
1483         D3DPSREGISTER_Color_Ambient = 3,
1484         D3DPSREGISTER_Color_Diffuse = 4,
1485         D3DPSREGISTER_Color_Specular = 5,
1486         D3DPSREGISTER_Color_Glow = 6,
1487         D3DPSREGISTER_Color_Pants = 7,
1488         D3DPSREGISTER_Color_Shirt = 8,
1489         D3DPSREGISTER_DeferredColor_Ambient = 9,
1490         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1491         D3DPSREGISTER_DeferredColor_Specular = 11,
1492         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1493         D3DPSREGISTER_DeferredMod_Specular = 13,
1494         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1495         D3DPSREGISTER_EyePosition = 15, // unused
1496         D3DPSREGISTER_FogColor = 16,
1497         D3DPSREGISTER_FogHeightFade = 17,
1498         D3DPSREGISTER_FogPlane = 18,
1499         D3DPSREGISTER_FogPlaneViewDist = 19,
1500         D3DPSREGISTER_FogRangeRecip = 20,
1501         D3DPSREGISTER_LightColor = 21,
1502         D3DPSREGISTER_LightDir = 22, // unused
1503         D3DPSREGISTER_LightPosition = 23,
1504         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1505         D3DPSREGISTER_PixelSize = 25,
1506         D3DPSREGISTER_ReflectColor = 26,
1507         D3DPSREGISTER_ReflectFactor = 27,
1508         D3DPSREGISTER_ReflectOffset = 28,
1509         D3DPSREGISTER_RefractColor = 29,
1510         D3DPSREGISTER_Saturation = 30,
1511         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1512         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1513         D3DPSREGISTER_ScreenToDepth = 33,
1514         D3DPSREGISTER_ShadowMap_Parameters = 34,
1515         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1516         D3DPSREGISTER_SpecularPower = 36,
1517         D3DPSREGISTER_UserVec1 = 37,
1518         D3DPSREGISTER_UserVec2 = 38,
1519         D3DPSREGISTER_UserVec3 = 39,
1520         D3DPSREGISTER_UserVec4 = 40,
1521         D3DPSREGISTER_ViewTintColor = 41,
1522         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1523         D3DPSREGISTER_BloomColorSubtract = 43,
1524         D3DPSREGISTER_ViewToLight = 44, // float4x4
1525         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1526         D3DPSREGISTER_NormalmapScrollBlend = 52,
1527         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1528         D3DPSREGISTER_OffsetMapping_Bias = 54,
1529         // next at 54
1530 }
1531 D3DPSREGISTER_t;
1532
1533 /// information about each possible shader permutation
1534 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1535 /// currently selected permutation
1536 r_hlsl_permutation_t *r_hlsl_permutation;
1537 /// storage for permutations linked in the hash table
1538 memexpandablearray_t r_hlsl_permutationarray;
1539
1540 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1541 {
1542         //unsigned int hashdepth = 0;
1543         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1544         r_hlsl_permutation_t *p;
1545         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1546         {
1547                 if (p->mode == mode && p->permutation == permutation)
1548                 {
1549                         //if (hashdepth > 10)
1550                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1551                         return p;
1552                 }
1553                 //hashdepth++;
1554         }
1555         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1556         p->mode = mode;
1557         p->permutation = permutation;
1558         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1559         r_hlsl_permutationhash[mode][hashindex] = p;
1560         //if (hashdepth > 10)
1561         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1562         return p;
1563 }
1564
1565 #include <d3dx9.h>
1566 //#include <d3dx9shader.h>
1567 //#include <d3dx9mesh.h>
1568
1569 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1570 {
1571         DWORD *vsbin = NULL;
1572         DWORD *psbin = NULL;
1573         fs_offset_t vsbinsize;
1574         fs_offset_t psbinsize;
1575 //      IDirect3DVertexShader9 *vs = NULL;
1576 //      IDirect3DPixelShader9 *ps = NULL;
1577         ID3DXBuffer *vslog = NULL;
1578         ID3DXBuffer *vsbuffer = NULL;
1579         ID3DXConstantTable *vsconstanttable = NULL;
1580         ID3DXBuffer *pslog = NULL;
1581         ID3DXBuffer *psbuffer = NULL;
1582         ID3DXConstantTable *psconstanttable = NULL;
1583         int vsresult = 0;
1584         int psresult = 0;
1585         char temp[MAX_INPUTLINE];
1586         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1587         char vabuf[1024];
1588         qboolean debugshader = gl_paranoid.integer != 0;
1589         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1590         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1591         if (!debugshader)
1592         {
1593                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1594                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1595         }
1596         if ((!vsbin && vertstring) || (!psbin && fragstring))
1597         {
1598                 const char* dllnames_d3dx9 [] =
1599                 {
1600                         "d3dx9_43.dll",
1601                         "d3dx9_42.dll",
1602                         "d3dx9_41.dll",
1603                         "d3dx9_40.dll",
1604                         "d3dx9_39.dll",
1605                         "d3dx9_38.dll",
1606                         "d3dx9_37.dll",
1607                         "d3dx9_36.dll",
1608                         "d3dx9_35.dll",
1609                         "d3dx9_34.dll",
1610                         "d3dx9_33.dll",
1611                         "d3dx9_32.dll",
1612                         "d3dx9_31.dll",
1613                         "d3dx9_30.dll",
1614                         "d3dx9_29.dll",
1615                         "d3dx9_28.dll",
1616                         "d3dx9_27.dll",
1617                         "d3dx9_26.dll",
1618                         "d3dx9_25.dll",
1619                         "d3dx9_24.dll",
1620                         NULL
1621                 };
1622                 dllhandle_t d3dx9_dll = NULL;
1623                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1624                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1625                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1626                 dllfunction_t d3dx9_dllfuncs[] =
1627                 {
1628                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1629                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1630                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1631                         {NULL, NULL}
1632                 };
1633                 // 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...
1634 #ifndef ID3DXBuffer_GetBufferPointer
1635 #if !defined(__cplusplus) || defined(CINTERFACE)
1636 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1637 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1638 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1639 #else
1640 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1641 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1642 #define ID3DXBuffer_Release(p)            (p)->Release()
1643 #endif
1644 #endif
1645                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1646                 {
1647                         DWORD shaderflags = 0;
1648                         if (debugshader)
1649                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1650                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1651                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1652                         if (vertstring && vertstring[0])
1653                         {
1654                                 if (debugshader)
1655                                 {
1656                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1657                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1658                                 }
1659                                 else
1660                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1661                                 if (vsbuffer)
1662                                 {
1663                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1664                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1665                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1666                                         ID3DXBuffer_Release(vsbuffer);
1667                                 }
1668                                 if (vslog)
1669                                 {
1670                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1671                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1672                                         ID3DXBuffer_Release(vslog);
1673                                 }
1674                         }
1675                         if (fragstring && fragstring[0])
1676                         {
1677                                 if (debugshader)
1678                                 {
1679                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1680                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1681                                 }
1682                                 else
1683                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1684                                 if (psbuffer)
1685                                 {
1686                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1687                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1688                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1689                                         ID3DXBuffer_Release(psbuffer);
1690                                 }
1691                                 if (pslog)
1692                                 {
1693                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1694                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1695                                         ID3DXBuffer_Release(pslog);
1696                                 }
1697                         }
1698                         Sys_UnloadLibrary(&d3dx9_dll);
1699                 }
1700                 else
1701                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1702         }
1703         if (vsbin && psbin)
1704         {
1705                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1706                 if (FAILED(vsresult))
1707                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1708                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1709                 if (FAILED(psresult))
1710                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1711         }
1712         // free the shader data
1713         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1714         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1715 }
1716
1717 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1718 {
1719         int i;
1720         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1721         int vertstring_length = 0;
1722         int geomstring_length = 0;
1723         int fragstring_length = 0;
1724         char *t;
1725         char *sourcestring;
1726         char *vertstring, *geomstring, *fragstring;
1727         char permutationname[256];
1728         char cachename[256];
1729         int vertstrings_count = 0;
1730         int geomstrings_count = 0;
1731         int fragstrings_count = 0;
1732         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1733         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1734         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1735
1736         if (p->compiled)
1737                 return;
1738         p->compiled = true;
1739         p->vertexshader = NULL;
1740         p->pixelshader = NULL;
1741
1742         permutationname[0] = 0;
1743         cachename[0] = 0;
1744         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1745
1746         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1747         strlcat(cachename, "hlsl/", sizeof(cachename));
1748
1749         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1750         vertstrings_count = 0;
1751         geomstrings_count = 0;
1752         fragstrings_count = 0;
1753         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1754         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1755         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1756
1757         // the first pretext is which type of shader to compile as
1758         // (later these will all be bound together as a program object)
1759         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1760         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1761         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1762
1763         // the second pretext is the mode (for example a light source)
1764         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1765         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1766         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1767         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1768         strlcat(cachename, modeinfo->name, sizeof(cachename));
1769
1770         // now add all the permutation pretexts
1771         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1772         {
1773                 if (permutation & (1<<i))
1774                 {
1775                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1776                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1777                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1778                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1779                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1780                 }
1781                 else
1782                 {
1783                         // keep line numbers correct
1784                         vertstrings_list[vertstrings_count++] = "\n";
1785                         geomstrings_list[geomstrings_count++] = "\n";
1786                         fragstrings_list[fragstrings_count++] = "\n";
1787                 }
1788         }
1789
1790         // add static parms
1791         R_CompileShader_AddStaticParms(mode, permutation);
1792         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1793         vertstrings_count += shaderstaticparms_count;
1794         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1795         geomstrings_count += shaderstaticparms_count;
1796         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1797         fragstrings_count += shaderstaticparms_count;
1798
1799         // replace spaces in the cachename with _ characters
1800         for (i = 0;cachename[i];i++)
1801                 if (cachename[i] == ' ')
1802                         cachename[i] = '_';
1803
1804         // now append the shader text itself
1805         vertstrings_list[vertstrings_count++] = sourcestring;
1806         geomstrings_list[geomstrings_count++] = sourcestring;
1807         fragstrings_list[fragstrings_count++] = sourcestring;
1808
1809         vertstring_length = 0;
1810         for (i = 0;i < vertstrings_count;i++)
1811                 vertstring_length += (int)strlen(vertstrings_list[i]);
1812         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1813         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1814                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1815
1816         geomstring_length = 0;
1817         for (i = 0;i < geomstrings_count;i++)
1818                 geomstring_length += (int)strlen(geomstrings_list[i]);
1819         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1820         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1821                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1822
1823         fragstring_length = 0;
1824         for (i = 0;i < fragstrings_count;i++)
1825                 fragstring_length += (int)strlen(fragstrings_list[i]);
1826         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1827         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1828                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1829
1830         // try to load the cached shader, or generate one
1831         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1832
1833         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1834                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1835         else
1836                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1837
1838         // free the strings
1839         if (vertstring)
1840                 Mem_Free(vertstring);
1841         if (geomstring)
1842                 Mem_Free(geomstring);
1843         if (fragstring)
1844                 Mem_Free(fragstring);
1845         if (sourcestring)
1846                 Mem_Free(sourcestring);
1847 }
1848
1849 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1850 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1851 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);}
1852 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);}
1853 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);}
1854 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);}
1855
1856 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1857 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1858 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);}
1859 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);}
1860 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);}
1861 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);}
1862
1863 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1864 {
1865         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1866         if (r_hlsl_permutation != perm)
1867         {
1868                 r_hlsl_permutation = perm;
1869                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1870                 {
1871                         if (!r_hlsl_permutation->compiled)
1872                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1873                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1874                         {
1875                                 // remove features until we find a valid permutation
1876                                 int i;
1877                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1878                                 {
1879                                         // reduce i more quickly whenever it would not remove any bits
1880                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1881                                         if (!(permutation & j))
1882                                                 continue;
1883                                         permutation -= j;
1884                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1885                                         if (!r_hlsl_permutation->compiled)
1886                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1887                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1888                                                 break;
1889                                 }
1890                                 if (i >= SHADERPERMUTATION_COUNT)
1891                                 {
1892                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1893                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1894                                         return; // no bit left to clear, entire mode is broken
1895                                 }
1896                         }
1897                 }
1898                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1899                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1900         }
1901         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1902         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1903         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1904 }
1905 #endif
1906
1907 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1908 {
1909         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1910         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1911         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1912         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1913 }
1914
1915 void R_GLSL_Restart_f(void)
1916 {
1917         unsigned int i, limit;
1918         switch(vid.renderpath)
1919         {
1920         case RENDERPATH_D3D9:
1921 #ifdef SUPPORTD3D
1922                 {
1923                         r_hlsl_permutation_t *p;
1924                         r_hlsl_permutation = NULL;
1925                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1926                         for (i = 0;i < limit;i++)
1927                         {
1928                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1929                                 {
1930                                         if (p->vertexshader)
1931                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1932                                         if (p->pixelshader)
1933                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1934                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1935                                 }
1936                         }
1937                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1938                 }
1939 #endif
1940                 break;
1941         case RENDERPATH_D3D10:
1942                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1943                 break;
1944         case RENDERPATH_D3D11:
1945                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1946                 break;
1947         case RENDERPATH_GL20:
1948         case RENDERPATH_GLES2:
1949                 {
1950                         r_glsl_permutation_t *p;
1951                         r_glsl_permutation = NULL;
1952                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1953                         for (i = 0;i < limit;i++)
1954                         {
1955                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1956                                 {
1957                                         GL_Backend_FreeProgram(p->program);
1958                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1959                                 }
1960                         }
1961                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1962                 }
1963                 break;
1964         case RENDERPATH_GL11:
1965         case RENDERPATH_GL13:
1966         case RENDERPATH_GLES1:
1967                 break;
1968         case RENDERPATH_SOFT:
1969                 break;
1970         }
1971 }
1972
1973 static void R_GLSL_DumpShader_f(void)
1974 {
1975         int i, language, mode, dupe;
1976         char *text;
1977         shadermodeinfo_t *modeinfo;
1978         qfile_t *file;
1979
1980         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1981         {
1982                 modeinfo = shadermodeinfo[language];
1983                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1984                 {
1985                         // don't dump the same file multiple times (most or all shaders come from the same file)
1986                         for (dupe = mode - 1;dupe >= 0;dupe--)
1987                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1988                                         break;
1989                         if (dupe >= 0)
1990                                 continue;
1991                         text = modeinfo[mode].builtinstring;
1992                         if (!text)
1993                                 continue;
1994                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1995                         if (file)
1996                         {
1997                                 FS_Print(file, "/* The engine may define the following macros:\n");
1998                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1999                                 for (i = 0;i < SHADERMODE_COUNT;i++)
2000                                         FS_Print(file, modeinfo[i].pretext);
2001                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2002                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2003                                 FS_Print(file, "*/\n");
2004                                 FS_Print(file, text);
2005                                 FS_Close(file);
2006                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2007                         }
2008                         else
2009                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2010                 }
2011         }
2012 }
2013
2014 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2015 {
2016         unsigned int permutation = 0;
2017         if (r_trippy.integer && !notrippy)
2018                 permutation |= SHADERPERMUTATION_TRIPPY;
2019         permutation |= SHADERPERMUTATION_VIEWTINT;
2020         if (first)
2021                 permutation |= SHADERPERMUTATION_DIFFUSE;
2022         if (second)
2023                 permutation |= SHADERPERMUTATION_SPECULAR;
2024         if (texturemode == GL_MODULATE)
2025                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2026         else if (texturemode == GL_ADD)
2027                 permutation |= SHADERPERMUTATION_GLOW;
2028         else if (texturemode == GL_DECAL)
2029                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2030         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2031                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2032         if (suppresstexalpha)
2033                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2034         if (!second)
2035                 texturemode = GL_MODULATE;
2036         if (vid.allowalphatocoverage)
2037                 GL_AlphaToCoverage(false);
2038         switch (vid.renderpath)
2039         {
2040         case RENDERPATH_D3D9:
2041 #ifdef SUPPORTD3D
2042                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2043                 R_Mesh_TexBind(GL20TU_FIRST , first );
2044                 R_Mesh_TexBind(GL20TU_SECOND, second);
2045                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2046                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2047 #endif
2048                 break;
2049         case RENDERPATH_D3D10:
2050                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2051                 break;
2052         case RENDERPATH_D3D11:
2053                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2054                 break;
2055         case RENDERPATH_GL20:
2056         case RENDERPATH_GLES2:
2057                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2058                 if (r_glsl_permutation->tex_Texture_First >= 0)
2059                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2060                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2061                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2062                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2063                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2064                 break;
2065         case RENDERPATH_GL13:
2066         case RENDERPATH_GLES1:
2067                 R_Mesh_TexBind(0, first );
2068                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2069                 R_Mesh_TexMatrix(0, NULL);
2070                 R_Mesh_TexBind(1, second);
2071                 if (second)
2072                 {
2073                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2074                         R_Mesh_TexMatrix(1, NULL);
2075                 }
2076                 break;
2077         case RENDERPATH_GL11:
2078                 R_Mesh_TexBind(0, first );
2079                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2080                 R_Mesh_TexMatrix(0, NULL);
2081                 break;
2082         case RENDERPATH_SOFT:
2083                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2084                 R_Mesh_TexBind(GL20TU_FIRST , first );
2085                 R_Mesh_TexBind(GL20TU_SECOND, second);
2086                 break;
2087         }
2088 }
2089
2090 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2091 {
2092         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2093 }
2094
2095 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2096 {
2097         unsigned int permutation = 0;
2098         if (r_trippy.integer && !notrippy)
2099                 permutation |= SHADERPERMUTATION_TRIPPY;
2100         if (depthrgb)
2101                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2102         if (skeletal)
2103                 permutation |= SHADERPERMUTATION_SKELETAL;
2104
2105         if (vid.allowalphatocoverage)
2106                 GL_AlphaToCoverage(false);
2107         switch (vid.renderpath)
2108         {
2109         case RENDERPATH_D3D9:
2110 #ifdef SUPPORTD3D
2111                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2112 #endif
2113                 break;
2114         case RENDERPATH_D3D10:
2115                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2116                 break;
2117         case RENDERPATH_D3D11:
2118                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2119                 break;
2120         case RENDERPATH_GL20:
2121         case RENDERPATH_GLES2:
2122                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2123 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2124                 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);
2125 #endif
2126                 break;
2127         case RENDERPATH_GL13:
2128         case RENDERPATH_GLES1:
2129                 R_Mesh_TexBind(0, 0);
2130                 R_Mesh_TexBind(1, 0);
2131                 break;
2132         case RENDERPATH_GL11:
2133                 R_Mesh_TexBind(0, 0);
2134                 break;
2135         case RENDERPATH_SOFT:
2136                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2137                 break;
2138         }
2139 }
2140
2141 extern qboolean r_shadow_usingdeferredprepass;
2142 extern rtexture_t *r_shadow_attenuationgradienttexture;
2143 extern rtexture_t *r_shadow_attenuation2dtexture;
2144 extern rtexture_t *r_shadow_attenuation3dtexture;
2145 extern qboolean r_shadow_usingshadowmap2d;
2146 extern qboolean r_shadow_usingshadowmaportho;
2147 extern float r_shadow_modelshadowmap_texturescale[4];
2148 extern float r_shadow_modelshadowmap_parameters[4];
2149 extern float r_shadow_lightshadowmap_texturescale[4];
2150 extern float r_shadow_lightshadowmap_parameters[4];
2151 extern qboolean r_shadow_shadowmapvsdct;
2152 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2153 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2154 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2155 extern matrix4x4_t r_shadow_shadowmapmatrix;
2156 extern int r_shadow_prepass_width;
2157 extern int r_shadow_prepass_height;
2158 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2159 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2160 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2161 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2162
2163 #define BLENDFUNC_ALLOWS_COLORMOD      1
2164 #define BLENDFUNC_ALLOWS_FOG           2
2165 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2166 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2167 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2168 static int R_BlendFuncFlags(int src, int dst)
2169 {
2170         int r = 0;
2171
2172         // a blendfunc allows colormod if:
2173         // a) it can never keep the destination pixel invariant, or
2174         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2175         // this is to prevent unintended side effects from colormod
2176
2177         // a blendfunc allows fog if:
2178         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2179         // this is to prevent unintended side effects from fog
2180
2181         // these checks are the output of fogeval.pl
2182
2183         r |= BLENDFUNC_ALLOWS_COLORMOD;
2184         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2185         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2186         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2187         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2188         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2189         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2190         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2191         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2192         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2193         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2194         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2195         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2196         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2197         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2198         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2199         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2200         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2201         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2202         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2203         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2204         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2205
2206         return r;
2207 }
2208
2209 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)
2210 {
2211         // select a permutation of the lighting shader appropriate to this
2212         // combination of texture, entity, light source, and fogging, only use the
2213         // minimum features necessary to avoid wasting rendering time in the
2214         // fragment shader on features that are not being used
2215         unsigned int permutation = 0;
2216         unsigned int mode = 0;
2217         int blendfuncflags;
2218         static float dummy_colormod[3] = {1, 1, 1};
2219         float *colormod = rsurface.colormod;
2220         float m16f[16];
2221         matrix4x4_t tempmatrix;
2222         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2223         if (r_trippy.integer && !notrippy)
2224                 permutation |= SHADERPERMUTATION_TRIPPY;
2225         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2226                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2227         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2228                 permutation |= SHADERPERMUTATION_OCCLUDE;
2229         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2230                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2231         if (rsurfacepass == RSURFPASS_BACKGROUND)
2232         {
2233                 // distorted background
2234                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2235                 {
2236                         mode = SHADERMODE_WATER;
2237                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2238                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2239                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2240                         {
2241                                 // this is the right thing to do for wateralpha
2242                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2243                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2244                         }
2245                         else
2246                         {
2247                                 // this is the right thing to do for entity alpha
2248                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2249                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2250                         }
2251                 }
2252                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2253                 {
2254                         mode = SHADERMODE_REFRACTION;
2255                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2256                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2257                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2258                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2259                 }
2260                 else
2261                 {
2262                         mode = SHADERMODE_GENERIC;
2263                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2264                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2265                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2266                 }
2267                 if (vid.allowalphatocoverage)
2268                         GL_AlphaToCoverage(false);
2269         }
2270         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2271         {
2272                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2273                 {
2274                         switch(rsurface.texture->offsetmapping)
2275                         {
2276                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2277                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2278                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2279                         case OFFSETMAPPING_OFF: break;
2280                         }
2281                 }
2282                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2283                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2284                 // normalmap (deferred prepass), may use alpha test on diffuse
2285                 mode = SHADERMODE_DEFERREDGEOMETRY;
2286                 GL_BlendFunc(GL_ONE, GL_ZERO);
2287                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2288                 if (vid.allowalphatocoverage)
2289                         GL_AlphaToCoverage(false);
2290         }
2291         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2292         {
2293                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2294                 {
2295                         switch(rsurface.texture->offsetmapping)
2296                         {
2297                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2298                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2299                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2300                         case OFFSETMAPPING_OFF: break;
2301                         }
2302                 }
2303                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2304                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2305                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2306                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2307                 // light source
2308                 mode = SHADERMODE_LIGHTSOURCE;
2309                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2310                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2311                 if (diffusescale > 0)
2312                         permutation |= SHADERPERMUTATION_DIFFUSE;
2313                 if (specularscale > 0)
2314                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2315                 if (r_refdef.fogenabled)
2316                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2317                 if (rsurface.texture->colormapping)
2318                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2319                 if (r_shadow_usingshadowmap2d)
2320                 {
2321                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2322                         if(r_shadow_shadowmapvsdct)
2323                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2324
2325                         if (r_shadow_shadowmap2ddepthbuffer)
2326                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2327                 }
2328                 if (rsurface.texture->reflectmasktexture)
2329                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2330                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2331                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2332                 if (vid.allowalphatocoverage)
2333                         GL_AlphaToCoverage(false);
2334         }
2335         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2336         {
2337                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2338                 {
2339                         switch(rsurface.texture->offsetmapping)
2340                         {
2341                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2342                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2343                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2344                         case OFFSETMAPPING_OFF: break;
2345                         }
2346                 }
2347                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2348                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2349                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2350                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2351                 // unshaded geometry (fullbright or ambient model lighting)
2352                 mode = SHADERMODE_FLATCOLOR;
2353                 ambientscale = diffusescale = specularscale = 0;
2354                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2355                         permutation |= SHADERPERMUTATION_GLOW;
2356                 if (r_refdef.fogenabled)
2357                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2358                 if (rsurface.texture->colormapping)
2359                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2360                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2361                 {
2362                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2363                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2364
2365                         if (r_shadow_shadowmap2ddepthbuffer)
2366                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2367                 }
2368                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2369                         permutation |= SHADERPERMUTATION_REFLECTION;
2370                 if (rsurface.texture->reflectmasktexture)
2371                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2372                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2373                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2374                 // when using alphatocoverage, we don't need alphakill
2375                 if (vid.allowalphatocoverage)
2376                 {
2377                         if (r_transparent_alphatocoverage.integer)
2378                         {
2379                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2380                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2381                         }
2382                         else
2383                                 GL_AlphaToCoverage(false);
2384                 }
2385         }
2386         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2387         {
2388                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2389                 {
2390                         switch(rsurface.texture->offsetmapping)
2391                         {
2392                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2393                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2394                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2395                         case OFFSETMAPPING_OFF: break;
2396                         }
2397                 }
2398                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2399                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2400                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2401                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2402                 // directional model lighting
2403                 mode = SHADERMODE_LIGHTDIRECTION;
2404                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2405                         permutation |= SHADERPERMUTATION_GLOW;
2406                 permutation |= SHADERPERMUTATION_DIFFUSE;
2407                 if (specularscale > 0)
2408                         permutation |= SHADERPERMUTATION_SPECULAR;
2409                 if (r_refdef.fogenabled)
2410                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2411                 if (rsurface.texture->colormapping)
2412                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2413                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2414                 {
2415                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2416                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2417
2418                         if (r_shadow_shadowmap2ddepthbuffer)
2419                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2420                 }
2421                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2422                         permutation |= SHADERPERMUTATION_REFLECTION;
2423                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2424                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2425                 if (rsurface.texture->reflectmasktexture)
2426                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2427                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2428                 {
2429                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2430                         if (r_shadow_bouncegrid_state.directional)
2431                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2432                 }
2433                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2434                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435                 // when using alphatocoverage, we don't need alphakill
2436                 if (vid.allowalphatocoverage)
2437                 {
2438                         if (r_transparent_alphatocoverage.integer)
2439                         {
2440                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2441                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2442                         }
2443                         else
2444                                 GL_AlphaToCoverage(false);
2445                 }
2446         }
2447         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2448         {
2449                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2450                 {
2451                         switch(rsurface.texture->offsetmapping)
2452                         {
2453                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2454                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2455                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2456                         case OFFSETMAPPING_OFF: break;
2457                         }
2458                 }
2459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2460                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2461                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2462                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2463                 // ambient model lighting
2464                 mode = SHADERMODE_LIGHTDIRECTION;
2465                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2466                         permutation |= SHADERPERMUTATION_GLOW;
2467                 if (r_refdef.fogenabled)
2468                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2469                 if (rsurface.texture->colormapping)
2470                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2471                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2472                 {
2473                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2474                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2475
2476                         if (r_shadow_shadowmap2ddepthbuffer)
2477                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2478                 }
2479                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2480                         permutation |= SHADERPERMUTATION_REFLECTION;
2481                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2482                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2483                 if (rsurface.texture->reflectmasktexture)
2484                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2485                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2486                 {
2487                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2488                         if (r_shadow_bouncegrid_state.directional)
2489                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2490                 }
2491                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2492                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2493                 // when using alphatocoverage, we don't need alphakill
2494                 if (vid.allowalphatocoverage)
2495                 {
2496                         if (r_transparent_alphatocoverage.integer)
2497                         {
2498                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2499                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2500                         }
2501                         else
2502                                 GL_AlphaToCoverage(false);
2503                 }
2504         }
2505         else
2506         {
2507                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2508                 {
2509                         switch(rsurface.texture->offsetmapping)
2510                         {
2511                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2512                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2513                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2514                         case OFFSETMAPPING_OFF: break;
2515                         }
2516                 }
2517                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2518                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2519                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2520                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2521                 // lightmapped wall
2522                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2523                         permutation |= SHADERPERMUTATION_GLOW;
2524                 if (r_refdef.fogenabled)
2525                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2526                 if (rsurface.texture->colormapping)
2527                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2528                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2529                 {
2530                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2531                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2532
2533                         if (r_shadow_shadowmap2ddepthbuffer)
2534                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2535                 }
2536                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2537                         permutation |= SHADERPERMUTATION_REFLECTION;
2538                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2539                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2540                 if (rsurface.texture->reflectmasktexture)
2541                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2542                 if (FAKELIGHT_ENABLED)
2543                 {
2544                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2545                         mode = SHADERMODE_FAKELIGHT;
2546                         permutation |= SHADERPERMUTATION_DIFFUSE;
2547                         if (specularscale > 0)
2548                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2549                 }
2550                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2551                 {
2552                         // deluxemapping (light direction texture)
2553                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2554                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2555                         else
2556                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2557                         permutation |= SHADERPERMUTATION_DIFFUSE;
2558                         if (specularscale > 0)
2559                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2560                 }
2561                 else if (r_glsl_deluxemapping.integer >= 2)
2562                 {
2563                         // fake deluxemapping (uniform light direction in tangentspace)
2564                         if (rsurface.uselightmaptexture)
2565                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2566                         else
2567                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2568                         permutation |= SHADERPERMUTATION_DIFFUSE;
2569                         if (specularscale > 0)
2570                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2571                 }
2572                 else if (rsurface.uselightmaptexture)
2573                 {
2574                         // ordinary lightmapping (q1bsp, q3bsp)
2575                         mode = SHADERMODE_LIGHTMAP;
2576                 }
2577                 else
2578                 {
2579                         // ordinary vertex coloring (q3bsp)
2580                         mode = SHADERMODE_VERTEXCOLOR;
2581                 }
2582                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2583                 {
2584                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2585                         if (r_shadow_bouncegrid_state.directional)
2586                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2587                 }
2588                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2589                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2590                 // when using alphatocoverage, we don't need alphakill
2591                 if (vid.allowalphatocoverage)
2592                 {
2593                         if (r_transparent_alphatocoverage.integer)
2594                         {
2595                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2596                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2597                         }
2598                         else
2599                                 GL_AlphaToCoverage(false);
2600                 }
2601         }
2602         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2603                 colormod = dummy_colormod;
2604         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2605                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2606         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2607                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2608         switch(vid.renderpath)
2609         {
2610         case RENDERPATH_D3D9:
2611 #ifdef SUPPORTD3D
2612                 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);
2613                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2614                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2615                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2616                 if (mode == SHADERMODE_LIGHTSOURCE)
2617                 {
2618                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2619                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2620                 }
2621                 else
2622                 {
2623                         if (mode == SHADERMODE_LIGHTDIRECTION)
2624                         {
2625                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2626                         }
2627                 }
2628                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2629                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2630                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2631                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2632                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2633
2634                 if (mode == SHADERMODE_LIGHTSOURCE)
2635                 {
2636                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2637                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2638                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2639                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2640                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2641
2642                         // additive passes are only darkened by fog, not tinted
2643                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2644                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2645                 }
2646                 else
2647                 {
2648                         if (mode == SHADERMODE_FLATCOLOR)
2649                         {
2650                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2651                         }
2652                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2653                         {
2654                                 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]);
2655                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2656                                 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);
2657                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2658                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2659                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2660                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2661                         }
2662                         else
2663                         {
2664                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2665                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2666                                 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);
2667                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2668                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2669                         }
2670                         // additive passes are only darkened by fog, not tinted
2671                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2672                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2673                         else
2674                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2675                         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);
2676                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2677                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2678                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2679                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2680                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2681                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2682                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2683                         if (mode == SHADERMODE_WATER)
2684                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2685                 }
2686                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2687                 {
2688                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2689                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2690                 }
2691                 else
2692                 {
2693                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2694                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2695                 }
2696                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2697                 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));
2698                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2699                 if (rsurface.texture->pantstexture)
2700                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2701                 else
2702                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2703                 if (rsurface.texture->shirttexture)
2704                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2705                 else
2706                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2707                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2708                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2709                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2710                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2711                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2712                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2713                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2714                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2715                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2716                         );
2717                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2718                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2719                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2720                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2721
2722                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2723                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2724                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2725                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2726                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2727                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2728                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2729                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2730                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2731                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2732                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2733                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2734                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2735                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2736                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2737                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2738                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2739                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2740                 {
2741                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2742                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2743                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2744                 }
2745                 else
2746                 {
2747                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2748                 }
2749 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2750                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2751                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2752                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2753                 {
2754                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2755                         if (rsurface.rtlight)
2756                         {
2757                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2758                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2759                         }
2760                 }
2761 #endif
2762                 break;
2763         case RENDERPATH_D3D10:
2764                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2765                 break;
2766         case RENDERPATH_D3D11:
2767                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2768                 break;
2769         case RENDERPATH_GL20:
2770         case RENDERPATH_GLES2:
2771                 if (!vid.useinterleavedarrays)
2772                 {
2773                         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);
2774                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2775                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2776                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2777                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2778                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2779                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2780                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2781                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2782                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2783                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2784                 }
2785                 else
2786                 {
2787                         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);
2788                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2789                 }
2790                 // this has to be after RSurf_PrepareVerticesForBatch
2791                 if (rsurface.batchskeletaltransform3x4buffer)
2792                         permutation |= SHADERPERMUTATION_SKELETAL;
2793                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2794 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2795                 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);
2796 #endif
2797                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2798                 if (mode == SHADERMODE_LIGHTSOURCE)
2799                 {
2800                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2801                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2802                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2803                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2804                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2805                         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);
2806         
2807                         // additive passes are only darkened by fog, not tinted
2808                         if (r_glsl_permutation->loc_FogColor >= 0)
2809                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2810                         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);
2811                 }
2812                 else
2813                 {
2814                         if (mode == SHADERMODE_FLATCOLOR)
2815                         {
2816                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2817                         }
2818                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2819                         {
2820                                 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]);
2821                                 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]);
2822                                 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);
2823                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2824                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2825                                 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]);
2826                                 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]);
2827                         }
2828                         else
2829                         {
2830                                 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]);
2831                                 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]);
2832                                 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);
2833                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2834                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2835                         }
2836                         // additive passes are only darkened by fog, not tinted
2837                         if (r_glsl_permutation->loc_FogColor >= 0)
2838                         {
2839                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2840                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2841                                 else
2842                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2843                         }
2844                         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);
2845                         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]);
2846                         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]);
2847                         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]);
2848                         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]);
2849                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2850                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2851                         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);
2852                         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]);
2853                 }
2854                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2855                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2856                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2857                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2858                 {
2859                         if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2860                         if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2861                 }
2862                 else
2863                 {
2864                         if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2865                         if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2866                 }
2867
2868                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2869                 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));
2870                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2871                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2872                 {
2873                         if (rsurface.texture->pantstexture)
2874                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2875                         else
2876                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2877                 }
2878                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2879                 {
2880                         if (rsurface.texture->shirttexture)
2881                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2882                         else
2883                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2884                 }
2885                 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]);
2886                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2887                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2888                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2889                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2890                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2891                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2892                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2893                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2894                         );
2895                 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);
2896                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2897                 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]);
2898                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2899                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2900                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2901
2902                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2903                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2904                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2905                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2906                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2907                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2908                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2909                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2910                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2911                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2912                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2913                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2914                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2915                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2916                 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);
2917                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2918                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2919                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2920                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2921                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2922                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2923                 {
2924                         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);
2925                         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);
2926                         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);
2927                 }
2928                 else
2929                 {
2930                         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);
2931                 }
2932                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2933                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2934                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2935                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2936                 {
2937                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2938                         if (rsurface.rtlight)
2939                         {
2940                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2941                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2942                         }
2943                 }
2944                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2945                 CHECKGLERROR
2946                 break;
2947         case RENDERPATH_GL11:
2948         case RENDERPATH_GL13:
2949         case RENDERPATH_GLES1:
2950                 break;
2951         case RENDERPATH_SOFT:
2952                 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);
2953                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2954                 R_SetupShader_SetPermutationSoft(mode, permutation);
2955                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2956                 if (mode == SHADERMODE_LIGHTSOURCE)
2957                 {
2958                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2959                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2960                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2961                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2962                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2963                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2964         
2965                         // additive passes are only darkened by fog, not tinted
2966                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2967                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2968                 }
2969                 else
2970                 {
2971                         if (mode == SHADERMODE_FLATCOLOR)
2972                         {
2973                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2974                         }
2975                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2976                         {
2977                                 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]);
2978                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2979                                 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);
2980                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2981                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2982                                 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]);
2983                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2984                         }
2985                         else
2986                         {
2987                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2988                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2989                                 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);
2990                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2991                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2992                         }
2993                         // additive passes are only darkened by fog, not tinted
2994                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2995                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2996                         else
2997                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2998                         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);
2999                         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]);
3000                         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]);
3001                         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]);
3002                         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]);
3003                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3004                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
3005                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3006                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
3007                 }
3008                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
3009                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
3010                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
3011                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
3012                 {
3013                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
3014                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
3015                 }
3016                 else
3017                 {
3018                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3019                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3020                 }
3021
3022                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3023                 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));
3024                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3025                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3026                 {
3027                         if (rsurface.texture->pantstexture)
3028                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3029                         else
3030                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3031                 }
3032                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3033                 {
3034                         if (rsurface.texture->shirttexture)
3035                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3036                         else
3037                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3038                 }
3039                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3040                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3041                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3042                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3043                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3044                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3045                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3046                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3047                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3048                         );
3049                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3050                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3051                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3052                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3053
3054                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3055                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3056                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3057                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3058                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3059                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3060                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3061                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3062                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3063                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3064                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3065                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3066                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3067                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3068                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3069                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3070                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3071                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3072                 {
3073                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3074                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3075                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3076                 }
3077                 else
3078                 {
3079                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3080                 }
3081 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3082                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3083                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3084                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3085                 {
3086                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3087                         if (rsurface.rtlight)
3088                         {
3089                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3090                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3091                         }
3092                 }
3093                 break;
3094         }
3095 }
3096
3097 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3098 {
3099         // select a permutation of the lighting shader appropriate to this
3100         // combination of texture, entity, light source, and fogging, only use the
3101         // minimum features necessary to avoid wasting rendering time in the
3102         // fragment shader on features that are not being used
3103         unsigned int permutation = 0;
3104         unsigned int mode = 0;
3105         const float *lightcolorbase = rtlight->currentcolor;
3106         float ambientscale = rtlight->ambientscale;
3107         float diffusescale = rtlight->diffusescale;
3108         float specularscale = rtlight->specularscale;
3109         // this is the location of the light in view space
3110         vec3_t viewlightorigin;
3111         // this transforms from view space (camera) to light space (cubemap)
3112         matrix4x4_t viewtolight;
3113         matrix4x4_t lighttoview;
3114         float viewtolight16f[16];
3115         // light source
3116         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3117         if (rtlight->currentcubemap != r_texture_whitecube)
3118                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3119         if (diffusescale > 0)
3120                 permutation |= SHADERPERMUTATION_DIFFUSE;
3121         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3122                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3123         if (r_shadow_usingshadowmap2d)
3124         {
3125                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3126                 if (r_shadow_shadowmapvsdct)
3127                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3128
3129                 if (r_shadow_shadowmap2ddepthbuffer)
3130                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3131         }
3132         if (vid.allowalphatocoverage)
3133                 GL_AlphaToCoverage(false);
3134         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3135         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3136         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3137         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3138         switch(vid.renderpath)
3139         {
3140         case RENDERPATH_D3D9:
3141 #ifdef SUPPORTD3D
3142                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3143                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3144                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3145                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3146                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3147                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3148                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3149                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3150                 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);
3151                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3152                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3153
3154                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3155                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3156                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3157                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3158                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3159 #endif
3160                 break;
3161         case RENDERPATH_D3D10:
3162                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3163                 break;
3164         case RENDERPATH_D3D11:
3165                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3166                 break;
3167         case RENDERPATH_GL20:
3168         case RENDERPATH_GLES2:
3169                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3170                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3171                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3172                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3173                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3174                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3175                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3176                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3177                 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);
3178                 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]);
3179                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3180
3181                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3182                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3183                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3184                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3185                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3186                 break;
3187         case RENDERPATH_GL11:
3188         case RENDERPATH_GL13:
3189         case RENDERPATH_GLES1:
3190                 break;
3191         case RENDERPATH_SOFT:
3192                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3193                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3194                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3195                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3196                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3197                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3198                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3199                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3200                 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);
3201                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3202                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3203
3204                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3205                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3206                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3207                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3208                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3209                 break;
3210         }
3211 }
3212
3213 #define SKINFRAME_HASH 1024
3214
3215 typedef struct
3216 {
3217         unsigned int loadsequence; // incremented each level change
3218         memexpandablearray_t array;
3219         skinframe_t *hash[SKINFRAME_HASH];
3220 }
3221 r_skinframe_t;
3222 r_skinframe_t r_skinframe;
3223
3224 void R_SkinFrame_PrepareForPurge(void)
3225 {
3226         r_skinframe.loadsequence++;
3227         // wrap it without hitting zero
3228         if (r_skinframe.loadsequence >= 200)
3229                 r_skinframe.loadsequence = 1;
3230 }
3231
3232 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3233 {
3234         if (!skinframe)
3235                 return;
3236         // mark the skinframe as used for the purging code
3237         skinframe->loadsequence = r_skinframe.loadsequence;
3238 }
3239
3240 void R_SkinFrame_Purge(void)
3241 {
3242         int i;
3243         skinframe_t *s;
3244         for (i = 0;i < SKINFRAME_HASH;i++)
3245         {
3246                 for (s = r_skinframe.hash[i];s;s = s->next)
3247                 {
3248                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3249                         {
3250                                 if (s->merged == s->base)
3251                                         s->merged = NULL;
3252                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3253                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3254                                 R_PurgeTexture(s->merged);s->merged = NULL;
3255                                 R_PurgeTexture(s->base  );s->base   = NULL;
3256                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3257                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3258                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3259                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3260                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3261                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3262                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3263                                 s->loadsequence = 0;
3264                         }
3265                 }
3266         }
3267 }
3268
3269 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3270         skinframe_t *item;
3271         char basename[MAX_QPATH];
3272
3273         Image_StripImageExtension(name, basename, sizeof(basename));
3274
3275         if( last == NULL ) {
3276                 int hashindex;
3277                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3278                 item = r_skinframe.hash[hashindex];
3279         } else {
3280                 item = last->next;
3281         }
3282
3283         // linearly search through the hash bucket
3284         for( ; item ; item = item->next ) {
3285                 if( !strcmp( item->basename, basename ) ) {
3286                         return item;
3287                 }
3288         }
3289         return NULL;
3290 }
3291
3292 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3293 {
3294         skinframe_t *item;
3295         int hashindex;
3296         char basename[MAX_QPATH];
3297
3298         Image_StripImageExtension(name, basename, sizeof(basename));
3299
3300         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3301         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3302                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3303                         break;
3304
3305         if (!item) {
3306                 rtexture_t *dyntexture;
3307                 // check whether its a dynamic texture
3308                 dyntexture = CL_GetDynTexture( basename );
3309                 if (!add && !dyntexture)
3310                         return NULL;
3311                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3312                 memset(item, 0, sizeof(*item));
3313                 strlcpy(item->basename, basename, sizeof(item->basename));
3314                 item->base = dyntexture; // either NULL or dyntexture handle
3315                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3316                 item->comparewidth = comparewidth;
3317                 item->compareheight = compareheight;
3318                 item->comparecrc = comparecrc;
3319                 item->next = r_skinframe.hash[hashindex];
3320                 r_skinframe.hash[hashindex] = item;
3321         }
3322         else if (textureflags & TEXF_FORCE_RELOAD)
3323         {
3324                 rtexture_t *dyntexture;
3325                 // check whether its a dynamic texture
3326                 dyntexture = CL_GetDynTexture( basename );
3327                 if (!add && !dyntexture)
3328                         return NULL;
3329                 if (item->merged == item->base)
3330                         item->merged = NULL;
3331                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3332                 R_PurgeTexture(item->stain );item->stain  = NULL;
3333                 R_PurgeTexture(item->merged);item->merged = NULL;
3334                 R_PurgeTexture(item->base  );item->base   = NULL;
3335                 R_PurgeTexture(item->pants );item->pants  = NULL;
3336                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3337                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3338                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3339                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3340                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3341         R_PurgeTexture(item->reflect);item->reflect = NULL;
3342                 item->loadsequence = 0;
3343         }
3344         else if( item->base == NULL )
3345         {
3346                 rtexture_t *dyntexture;
3347                 // check whether its a dynamic texture
3348                 // 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]
3349                 dyntexture = CL_GetDynTexture( basename );
3350                 item->base = dyntexture; // either NULL or dyntexture handle
3351         }
3352
3353         R_SkinFrame_MarkUsed(item);
3354         return item;
3355 }
3356
3357 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3358         { \
3359                 unsigned long long avgcolor[5], wsum; \
3360                 int pix, comp, w; \
3361                 avgcolor[0] = 0; \
3362                 avgcolor[1] = 0; \
3363                 avgcolor[2] = 0; \
3364                 avgcolor[3] = 0; \
3365                 avgcolor[4] = 0; \
3366                 wsum = 0; \
3367                 for(pix = 0; pix < cnt; ++pix) \
3368                 { \
3369                         w = 0; \
3370                         for(comp = 0; comp < 3; ++comp) \
3371                                 w += getpixel; \
3372                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3373                         { \
3374                                 ++wsum; \
3375                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3376                                 w = getpixel; \
3377                                 for(comp = 0; comp < 3; ++comp) \
3378                                         avgcolor[comp] += getpixel * w; \
3379                                 avgcolor[3] += w; \
3380                         } \
3381                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3382                         avgcolor[4] += getpixel; \
3383                 } \
3384                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3385                         avgcolor[3] = 1; \
3386                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3387                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3388                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3389                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3390         }
3391
3392 extern cvar_t gl_picmip;
3393 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3394 {
3395         int j;
3396         unsigned char *pixels;
3397         unsigned char *bumppixels;
3398         unsigned char *basepixels = NULL;
3399         int basepixels_width = 0;
3400         int basepixels_height = 0;
3401         skinframe_t *skinframe;
3402         rtexture_t *ddsbase = NULL;
3403         qboolean ddshasalpha = false;
3404         float ddsavgcolor[4];
3405         char basename[MAX_QPATH];
3406         int miplevel = R_PicmipForFlags(textureflags);
3407         int savemiplevel = miplevel;
3408         int mymiplevel;
3409         char vabuf[1024];
3410
3411         if (cls.state == ca_dedicated)
3412                 return NULL;
3413
3414         // return an existing skinframe if already loaded
3415         // if loading of the first image fails, don't make a new skinframe as it
3416         // would cause all future lookups of this to be missing
3417         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3418         if (skinframe && skinframe->base)
3419                 return skinframe;
3420
3421         Image_StripImageExtension(name, basename, sizeof(basename));
3422
3423         // check for DDS texture file first
3424         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3425         {
3426                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3427                 if (basepixels == NULL)
3428                         return NULL;
3429         }
3430
3431         // FIXME handle miplevel
3432
3433         if (developer_loading.integer)
3434                 Con_Printf("loading skin \"%s\"\n", name);
3435
3436         // we've got some pixels to store, so really allocate this new texture now
3437         if (!skinframe)
3438                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3439         textureflags &= ~TEXF_FORCE_RELOAD;
3440         skinframe->stain = NULL;
3441         skinframe->merged = NULL;
3442         skinframe->base = NULL;
3443         skinframe->pants = NULL;
3444         skinframe->shirt = NULL;
3445         skinframe->nmap = NULL;
3446         skinframe->gloss = NULL;
3447         skinframe->glow = NULL;
3448         skinframe->fog = NULL;
3449         skinframe->reflect = NULL;
3450         skinframe->hasalpha = false;
3451         // we could store the q2animname here too
3452
3453         if (ddsbase)
3454         {
3455                 skinframe->base = ddsbase;
3456                 skinframe->hasalpha = ddshasalpha;
3457                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3458                 if (r_loadfog && skinframe->hasalpha)
3459                         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);
3460                 //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]);
3461         }
3462         else
3463         {
3464                 basepixels_width = image_width;
3465                 basepixels_height = image_height;
3466                 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);
3467                 if (textureflags & TEXF_ALPHA)
3468                 {
3469                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3470                         {
3471                                 if (basepixels[j] < 255)
3472                                 {
3473                                         skinframe->hasalpha = true;
3474                                         break;
3475                                 }
3476                         }
3477                         if (r_loadfog && skinframe->hasalpha)
3478                         {
3479                                 // has transparent pixels
3480                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3481                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3482                                 {
3483                                         pixels[j+0] = 255;
3484                                         pixels[j+1] = 255;
3485                                         pixels[j+2] = 255;
3486                                         pixels[j+3] = basepixels[j+3];
3487                                 }
3488                                 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);
3489                                 Mem_Free(pixels);
3490                         }
3491                 }
3492                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3493 #ifndef USE_GLES2
3494                 //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]);
3495                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3496                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3497                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3498                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3499 #endif
3500         }
3501
3502         if (r_loaddds)
3503         {
3504                 mymiplevel = savemiplevel;
3505                 if (r_loadnormalmap)
3506                         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);
3507                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3508                 if (r_loadgloss)
3509                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3510                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3511                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3512                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3513         }
3514
3515         // _norm is the name used by tenebrae and has been adopted as standard
3516         if (r_loadnormalmap && skinframe->nmap == NULL)
3517         {
3518                 mymiplevel = savemiplevel;
3519                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3520                 {
3521                         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);
3522                         Mem_Free(pixels);
3523                         pixels = NULL;
3524                 }
3525                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3526                 {
3527                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3528                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3529                         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);
3530                         Mem_Free(pixels);
3531                         Mem_Free(bumppixels);
3532                 }
3533                 else if (r_shadow_bumpscale_basetexture.value > 0)
3534                 {
3535                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3536                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3537                         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);
3538                         Mem_Free(pixels);
3539                 }
3540 #ifndef USE_GLES2
3541                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3542                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3543 #endif
3544         }
3545
3546         // _luma is supported only for tenebrae compatibility
3547         // _glow is the preferred name
3548         mymiplevel = savemiplevel;
3549         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))))
3550         {
3551                 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);
3552 #ifndef USE_GLES2
3553                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3554                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3555 #endif
3556                 Mem_Free(pixels);pixels = NULL;
3557         }
3558
3559         mymiplevel = savemiplevel;
3560         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3561         {
3562                 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);
3563 #ifndef USE_GLES2
3564                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3565                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3566 #endif
3567                 Mem_Free(pixels);
3568                 pixels = NULL;
3569         }
3570
3571         mymiplevel = savemiplevel;
3572         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3573         {
3574                 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);
3575 #ifndef USE_GLES2
3576                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3577                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3578 #endif
3579                 Mem_Free(pixels);
3580                 pixels = NULL;
3581         }
3582
3583         mymiplevel = savemiplevel;
3584         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3585         {
3586                 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);
3587 #ifndef USE_GLES2
3588                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3589                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3590 #endif
3591                 Mem_Free(pixels);
3592                 pixels = NULL;
3593         }
3594
3595         mymiplevel = savemiplevel;
3596         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3597         {
3598                 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);
3599 #ifndef USE_GLES2
3600                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3601                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3602 #endif
3603                 Mem_Free(pixels);
3604                 pixels = NULL;
3605         }
3606
3607         if (basepixels)
3608                 Mem_Free(basepixels);
3609
3610         return skinframe;
3611 }
3612
3613 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3614 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3615 {
3616         int i;
3617         skinframe_t *skinframe;
3618         char vabuf[1024];
3619
3620         if (cls.state == ca_dedicated)
3621                 return NULL;
3622
3623         // if already loaded just return it, otherwise make a new skinframe
3624         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3625         if (skinframe->base)
3626                 return skinframe;
3627         textureflags &= ~TEXF_FORCE_RELOAD;
3628
3629         skinframe->stain = NULL;
3630         skinframe->merged = NULL;
3631         skinframe->base = NULL;
3632         skinframe->pants = NULL;
3633         skinframe->shirt = NULL;
3634         skinframe->nmap = NULL;
3635         skinframe->gloss = NULL;
3636         skinframe->glow = NULL;
3637         skinframe->fog = NULL;
3638         skinframe->reflect = NULL;
3639         skinframe->hasalpha = false;
3640
3641         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3642         if (!skindata)
3643                 return NULL;
3644
3645         if (developer_loading.integer)
3646                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3647
3648         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3649         {
3650                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3651                 unsigned char *b = a + width * height * 4;
3652                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3653                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3654                 Mem_Free(a);
3655         }
3656         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3657         if (textureflags & TEXF_ALPHA)
3658         {
3659                 for (i = 3;i < width * height * 4;i += 4)
3660                 {
3661                         if (skindata[i] < 255)
3662                         {
3663                                 skinframe->hasalpha = true;
3664                                 break;
3665                         }
3666                 }
3667                 if (r_loadfog && skinframe->hasalpha)
3668                 {
3669                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3670                         memcpy(fogpixels, skindata, width * height * 4);
3671                         for (i = 0;i < width * height * 4;i += 4)
3672                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3673                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3674                         Mem_Free(fogpixels);
3675                 }
3676         }
3677
3678         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3679         //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]);
3680
3681         return skinframe;
3682 }
3683
3684 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3685 {
3686         int i;
3687         int featuresmask;
3688         skinframe_t *skinframe;
3689
3690         if (cls.state == ca_dedicated)
3691                 return NULL;
3692
3693         // if already loaded just return it, otherwise make a new skinframe
3694         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3695         if (skinframe->base)
3696                 return skinframe;
3697         //textureflags &= ~TEXF_FORCE_RELOAD;
3698
3699         skinframe->stain = NULL;
3700         skinframe->merged = NULL;
3701         skinframe->base = NULL;
3702         skinframe->pants = NULL;
3703         skinframe->shirt = NULL;
3704         skinframe->nmap = NULL;
3705         skinframe->gloss = NULL;
3706         skinframe->glow = NULL;
3707         skinframe->fog = NULL;
3708         skinframe->reflect = NULL;
3709         skinframe->hasalpha = false;
3710
3711         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3712         if (!skindata)
3713                 return NULL;
3714
3715         if (developer_loading.integer)
3716                 Con_Printf("loading quake skin \"%s\"\n", name);
3717
3718         // 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)
3719         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3720         memcpy(skinframe->qpixels, skindata, width*height);
3721         skinframe->qwidth = width;
3722         skinframe->qheight = height;
3723
3724         featuresmask = 0;
3725         for (i = 0;i < width * height;i++)
3726                 featuresmask |= palette_featureflags[skindata[i]];
3727
3728         skinframe->hasalpha = false;
3729         // fence textures
3730         if (name[0] == '{')
3731                 skinframe->hasalpha = true;
3732         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3733         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3734         skinframe->qgeneratemerged = true;
3735         skinframe->qgeneratebase = skinframe->qhascolormapping;
3736         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3737
3738         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3739         //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]);
3740
3741         return skinframe;
3742 }
3743
3744 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3745 {
3746         int width;
3747         int height;
3748         unsigned char *skindata;
3749         char vabuf[1024];
3750
3751         if (!skinframe->qpixels)
3752                 return;
3753
3754         if (!skinframe->qhascolormapping)
3755                 colormapped = false;
3756
3757         if (colormapped)
3758         {
3759                 if (!skinframe->qgeneratebase)
3760                         return;
3761         }
3762         else
3763         {
3764                 if (!skinframe->qgeneratemerged)
3765                         return;
3766         }
3767
3768         width = skinframe->qwidth;
3769         height = skinframe->qheight;
3770         skindata = skinframe->qpixels;
3771
3772         if (skinframe->qgeneratenmap)
3773         {
3774                 unsigned char *a, *b;
3775                 skinframe->qgeneratenmap = false;
3776                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3777                 b = a + width * height * 4;
3778                 // use either a custom palette or the quake palette
3779                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3780                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3781                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3782                 Mem_Free(a);
3783         }
3784
3785         if (skinframe->qgenerateglow)
3786         {
3787                 skinframe->qgenerateglow = false;
3788                 if (skinframe->hasalpha) // fence textures
3789                         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 | TEXF_ALPHA, -1, palette_bgra_onlyfullbrights_transparent); // glow
3790                 else
3791                         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
3792         }
3793
3794         if (colormapped)
3795         {
3796                 skinframe->qgeneratebase = false;
3797                 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);
3798                 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);
3799                 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);
3800         }
3801         else
3802         {
3803                 skinframe->qgeneratemerged = false;
3804                 if (skinframe->hasalpha) // fence textures
3805                         skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, skinframe->glow ? palette_bgra_nofullbrights_transparent : palette_bgra_transparent);
3806                 else
3807                         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);
3808         }
3809
3810         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3811         {
3812                 Mem_Free(skinframe->qpixels);
3813                 skinframe->qpixels = NULL;
3814         }
3815 }
3816
3817 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)
3818 {
3819         int i;
3820         skinframe_t *skinframe;
3821         char vabuf[1024];
3822
3823         if (cls.state == ca_dedicated)
3824                 return NULL;
3825
3826         // if already loaded just return it, otherwise make a new skinframe
3827         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3828         if (skinframe->base)
3829                 return skinframe;
3830         textureflags &= ~TEXF_FORCE_RELOAD;
3831
3832         skinframe->stain = NULL;
3833         skinframe->merged = NULL;
3834         skinframe->base = NULL;
3835         skinframe->pants = NULL;
3836         skinframe->shirt = NULL;
3837         skinframe->nmap = NULL;
3838         skinframe->gloss = NULL;
3839         skinframe->glow = NULL;
3840         skinframe->fog = NULL;
3841         skinframe->reflect = NULL;
3842         skinframe->hasalpha = false;
3843
3844         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3845         if (!skindata)
3846                 return NULL;
3847
3848         if (developer_loading.integer)
3849                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3850
3851         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3852         if (textureflags & TEXF_ALPHA)
3853         {
3854                 for (i = 0;i < width * height;i++)
3855                 {
3856                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3857                         {
3858                                 skinframe->hasalpha = true;
3859                                 break;
3860                         }
3861                 }
3862                 if (r_loadfog && skinframe->hasalpha)
3863                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3864         }
3865
3866         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3867         //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]);
3868
3869         return skinframe;
3870 }
3871
3872 skinframe_t *R_SkinFrame_LoadMissing(void)
3873 {
3874         skinframe_t *skinframe;
3875
3876         if (cls.state == ca_dedicated)
3877                 return NULL;
3878
3879         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3880         skinframe->stain = NULL;
3881         skinframe->merged = NULL;
3882         skinframe->base = NULL;
3883         skinframe->pants = NULL;
3884         skinframe->shirt = NULL;
3885         skinframe->nmap = NULL;
3886         skinframe->gloss = NULL;
3887         skinframe->glow = NULL;
3888         skinframe->fog = NULL;
3889         skinframe->reflect = NULL;
3890         skinframe->hasalpha = false;
3891
3892         skinframe->avgcolor[0] = rand() / RAND_MAX;
3893         skinframe->avgcolor[1] = rand() / RAND_MAX;
3894         skinframe->avgcolor[2] = rand() / RAND_MAX;
3895         skinframe->avgcolor[3] = 1;
3896
3897         return skinframe;
3898 }
3899
3900 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3901 typedef struct suffixinfo_s
3902 {
3903         const char *suffix;
3904         qboolean flipx, flipy, flipdiagonal;
3905 }
3906 suffixinfo_t;
3907 static suffixinfo_t suffix[3][6] =
3908 {
3909         {
3910                 {"px",   false, false, false},
3911                 {"nx",   false, false, false},
3912                 {"py",   false, false, false},
3913                 {"ny",   false, false, false},
3914                 {"pz",   false, false, false},
3915                 {"nz",   false, false, false}
3916         },
3917         {
3918                 {"posx", false, false, false},
3919                 {"negx", false, false, false},
3920                 {"posy", false, false, false},
3921                 {"negy", false, false, false},
3922                 {"posz", false, false, false},
3923                 {"negz", false, false, false}
3924         },
3925         {
3926                 {"rt",    true, false,  true},
3927                 {"lf",   false,  true,  true},
3928                 {"ft",    true,  true, false},
3929                 {"bk",   false, false, false},
3930                 {"up",    true, false,  true},
3931                 {"dn",    true, false,  true}
3932         }
3933 };
3934
3935 static int componentorder[4] = {0, 1, 2, 3};
3936
3937 static rtexture_t *R_LoadCubemap(const char *basename)
3938 {
3939         int i, j, cubemapsize;
3940         unsigned char *cubemappixels, *image_buffer;
3941         rtexture_t *cubemaptexture;
3942         char name[256];
3943         // must start 0 so the first loadimagepixels has no requested width/height
3944         cubemapsize = 0;
3945         cubemappixels = NULL;
3946         cubemaptexture = NULL;
3947         // keep trying different suffix groups (posx, px, rt) until one loads
3948         for (j = 0;j < 3 && !cubemappixels;j++)
3949         {
3950                 // load the 6 images in the suffix group
3951                 for (i = 0;i < 6;i++)
3952                 {
3953                         // generate an image name based on the base and and suffix
3954                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3955                         // load it
3956                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3957                         {
3958                                 // an image loaded, make sure width and height are equal
3959                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3960                                 {
3961                                         // if this is the first image to load successfully, allocate the cubemap memory
3962                                         if (!cubemappixels && image_width >= 1)
3963                                         {
3964                                                 cubemapsize = image_width;
3965                                                 // note this clears to black, so unavailable sides are black
3966                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3967                                         }
3968                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3969                                         if (cubemappixels)
3970                                                 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);
3971                                 }
3972                                 else
3973                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3974                                 // free the image
3975                                 Mem_Free(image_buffer);
3976                         }
3977                 }
3978         }
3979         // if a cubemap loaded, upload it
3980         if (cubemappixels)
3981         {
3982                 if (developer_loading.integer)
3983                         Con_Printf("loading cubemap \"%s\"\n", basename);
3984
3985                 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);
3986                 Mem_Free(cubemappixels);
3987         }
3988         else
3989         {
3990                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3991                 if (developer_loading.integer)
3992                 {
3993                         Con_Printf("(tried tried images ");
3994                         for (j = 0;j < 3;j++)
3995                                 for (i = 0;i < 6;i++)
3996                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3997                         Con_Print(" and was unable to find any of them).\n");
3998                 }
3999         }
4000         return cubemaptexture;
4001 }
4002
4003 rtexture_t *R_GetCubemap(const char *basename)
4004 {
4005         int i;
4006         for (i = 0;i < r_texture_numcubemaps;i++)
4007                 if (r_texture_cubemaps[i] != NULL)
4008                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
4009                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
4010         if (i >= MAX_CUBEMAPS || !r_main_mempool)
4011                 return r_texture_whitecube;
4012         r_texture_numcubemaps++;
4013         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
4014         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
4015         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
4016         return r_texture_cubemaps[i]->texture;
4017 }
4018
4019 static void R_Main_FreeViewCache(void)
4020 {
4021         if (r_refdef.viewcache.entityvisible)
4022                 Mem_Free(r_refdef.viewcache.entityvisible);
4023         if (r_refdef.viewcache.world_pvsbits)
4024                 Mem_Free(r_refdef.viewcache.world_pvsbits);
4025         if (r_refdef.viewcache.world_leafvisible)
4026                 Mem_Free(r_refdef.viewcache.world_leafvisible);
4027         if (r_refdef.viewcache.world_surfacevisible)
4028                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4029         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4030 }
4031
4032 static void R_Main_ResizeViewCache(void)
4033 {
4034         int numentities = r_refdef.scene.numentities;
4035         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4036         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4037         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4038         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4039         if (r_refdef.viewcache.maxentities < numentities)
4040         {
4041                 r_refdef.viewcache.maxentities = numentities;
4042                 if (r_refdef.viewcache.entityvisible)
4043                         Mem_Free(r_refdef.viewcache.entityvisible);
4044                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4045         }
4046         if (r_refdef.viewcache.world_numclusters != numclusters)
4047         {
4048                 r_refdef.viewcache.world_numclusters = numclusters;
4049                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4050                 if (r_refdef.viewcache.world_pvsbits)
4051                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4052                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4053         }
4054         if (r_refdef.viewcache.world_numleafs != numleafs)
4055         {
4056                 r_refdef.viewcache.world_numleafs = numleafs;
4057                 if (r_refdef.viewcache.world_leafvisible)
4058                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4059                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4060         }
4061         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4062         {
4063                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4064                 if (r_refdef.viewcache.world_surfacevisible)
4065                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4066                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4067         }
4068 }
4069
4070 extern rtexture_t *loadingscreentexture;
4071 static void gl_main_start(void)
4072 {
4073         loadingscreentexture = NULL;
4074         r_texture_blanknormalmap = NULL;
4075         r_texture_white = NULL;
4076         r_texture_grey128 = NULL;
4077         r_texture_black = NULL;
4078         r_texture_whitecube = NULL;
4079         r_texture_normalizationcube = NULL;
4080         r_texture_fogattenuation = NULL;
4081         r_texture_fogheighttexture = NULL;
4082         r_texture_gammaramps = NULL;
4083         r_texture_numcubemaps = 0;
4084         r_uniformbufferalignment = 32;
4085
4086         r_loaddds = r_texture_dds_load.integer != 0;
4087         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4088
4089         switch(vid.renderpath)
4090         {
4091         case RENDERPATH_GL20:
4092         case RENDERPATH_D3D9:
4093         case RENDERPATH_D3D10:
4094         case RENDERPATH_D3D11:
4095         case RENDERPATH_SOFT:
4096         case RENDERPATH_GLES2:
4097                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4098                 Cvar_SetValueQuick(&gl_combine, 1);
4099                 Cvar_SetValueQuick(&r_glsl, 1);
4100                 r_loadnormalmap = true;
4101                 r_loadgloss = true;
4102                 r_loadfog = false;
4103 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4104                 if (vid.support.arb_uniform_buffer_object)
4105                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4106 #endif
4107                         break;
4108         case RENDERPATH_GL13:
4109         case RENDERPATH_GLES1:
4110                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4111                 Cvar_SetValueQuick(&gl_combine, 1);
4112                 Cvar_SetValueQuick(&r_glsl, 0);
4113                 r_loadnormalmap = false;
4114                 r_loadgloss = false;
4115                 r_loadfog = true;
4116                 break;
4117         case RENDERPATH_GL11:
4118                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4119                 Cvar_SetValueQuick(&gl_combine, 0);
4120                 Cvar_SetValueQuick(&r_glsl, 0);
4121                 r_loadnormalmap = false;
4122                 r_loadgloss = false;
4123                 r_loadfog = true;
4124                 break;
4125         }
4126
4127         R_AnimCache_Free();
4128         R_FrameData_Reset();
4129         R_BufferData_Reset();
4130
4131         r_numqueries = 0;
4132         r_maxqueries = 0;
4133         memset(r_queries, 0, sizeof(r_queries));
4134
4135         r_qwskincache = NULL;
4136         r_qwskincache_size = 0;
4137
4138         // due to caching of texture_t references, the collision cache must be reset
4139         Collision_Cache_Reset(true);
4140
4141         // set up r_skinframe loading system for textures
4142         memset(&r_skinframe, 0, sizeof(r_skinframe));
4143         r_skinframe.loadsequence = 1;
4144         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4145
4146         r_main_texturepool = R_AllocTexturePool();
4147         R_BuildBlankTextures();
4148         R_BuildNoTexture();
4149         if (vid.support.arb_texture_cube_map)
4150         {
4151                 R_BuildWhiteCube();
4152                 R_BuildNormalizationCube();
4153         }
4154         r_texture_fogattenuation = NULL;
4155         r_texture_fogheighttexture = NULL;
4156         r_texture_gammaramps = NULL;
4157         //r_texture_fogintensity = NULL;
4158         memset(&r_fb, 0, sizeof(r_fb));
4159         r_glsl_permutation = NULL;
4160         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4161         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4162 #ifdef SUPPORTD3D
4163         r_hlsl_permutation = NULL;
4164         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4165         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4166 #endif
4167         memset(&r_svbsp, 0, sizeof (r_svbsp));
4168
4169         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4170         r_texture_numcubemaps = 0;
4171
4172         r_refdef.fogmasktable_density = 0;
4173
4174 #ifdef __ANDROID__
4175         // For Steelstorm Android
4176         // FIXME CACHE the program and reload
4177         // FIXME see possible combinations for SS:BR android
4178         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4179         R_SetupShader_SetPermutationGLSL(0, 12);
4180         R_SetupShader_SetPermutationGLSL(0, 13);
4181         R_SetupShader_SetPermutationGLSL(0, 8388621);
4182         R_SetupShader_SetPermutationGLSL(3, 0);
4183         R_SetupShader_SetPermutationGLSL(3, 2048);
4184         R_SetupShader_SetPermutationGLSL(5, 0);
4185         R_SetupShader_SetPermutationGLSL(5, 2);
4186         R_SetupShader_SetPermutationGLSL(5, 2048);
4187         R_SetupShader_SetPermutationGLSL(5, 8388608);
4188         R_SetupShader_SetPermutationGLSL(11, 1);
4189         R_SetupShader_SetPermutationGLSL(11, 2049);
4190         R_SetupShader_SetPermutationGLSL(11, 8193);
4191         R_SetupShader_SetPermutationGLSL(11, 10241);
4192         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4193 #endif
4194 }
4195
4196 static void gl_main_shutdown(void)
4197 {
4198         R_AnimCache_Free();
4199         R_FrameData_Reset();
4200         R_BufferData_Reset();
4201
4202         R_Main_FreeViewCache();
4203
4204         switch(vid.renderpath)
4205         {
4206         case RENDERPATH_GL11:
4207         case RENDERPATH_GL13:
4208         case RENDERPATH_GL20:
4209         case RENDERPATH_GLES1:
4210         case RENDERPATH_GLES2:
4211 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4212                 if (r_maxqueries)
4213                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4214 #endif
4215                 break;
4216         case RENDERPATH_D3D9:
4217                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4218                 break;
4219         case RENDERPATH_D3D10:
4220                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4221                 break;
4222         case RENDERPATH_D3D11:
4223                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4224                 break;
4225         case RENDERPATH_SOFT:
4226                 break;
4227         }
4228
4229         r_numqueries = 0;
4230         r_maxqueries = 0;
4231         memset(r_queries, 0, sizeof(r_queries));
4232
4233         r_qwskincache = NULL;
4234         r_qwskincache_size = 0;
4235
4236         // clear out the r_skinframe state
4237         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4238         memset(&r_skinframe, 0, sizeof(r_skinframe));
4239
4240         if (r_svbsp.nodes)
4241                 Mem_Free(r_svbsp.nodes);
4242         memset(&r_svbsp, 0, sizeof (r_svbsp));
4243         R_FreeTexturePool(&r_main_texturepool);
4244         loadingscreentexture = NULL;
4245         r_texture_blanknormalmap = NULL;
4246         r_texture_white = NULL;
4247         r_texture_grey128 = NULL;
4248         r_texture_black = NULL;
4249         r_texture_whitecube = NULL;
4250         r_texture_normalizationcube = NULL;
4251         r_texture_fogattenuation = NULL;
4252         r_texture_fogheighttexture = NULL;
4253         r_texture_gammaramps = NULL;
4254         r_texture_numcubemaps = 0;
4255         //r_texture_fogintensity = NULL;
4256         memset(&r_fb, 0, sizeof(r_fb));
4257         R_GLSL_Restart_f();
4258
4259         r_glsl_permutation = NULL;
4260         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4261         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4262 #ifdef SUPPORTD3D
4263         r_hlsl_permutation = NULL;
4264         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4265         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4266 #endif
4267 }
4268
4269 static void gl_main_newmap(void)
4270 {
4271         // FIXME: move this code to client
4272         char *entities, entname[MAX_QPATH];
4273         if (r_qwskincache)
4274                 Mem_Free(r_qwskincache);
4275         r_qwskincache = NULL;
4276         r_qwskincache_size = 0;
4277         if (cl.worldmodel)
4278         {
4279                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4280                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4281                 {
4282                         CL_ParseEntityLump(entities);
4283                         Mem_Free(entities);
4284                         return;
4285                 }
4286                 if (cl.worldmodel->brush.entities)
4287                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4288         }
4289         R_Main_FreeViewCache();
4290
4291         R_FrameData_Reset();
4292         R_BufferData_Reset();
4293 }
4294
4295 void GL_Main_Init(void)
4296 {
4297         int i;
4298         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4299         R_InitShaderModeInfo();
4300
4301         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4302         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4303         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4304         if (gamemode == GAME_NEHAHRA)
4305         {
4306                 Cvar_RegisterVariable (&gl_fogenable);
4307                 Cvar_RegisterVariable (&gl_fogdensity);
4308                 Cvar_RegisterVariable (&gl_fogred);
4309                 Cvar_RegisterVariable (&gl_foggreen);
4310                 Cvar_RegisterVariable (&gl_fogblue);
4311                 Cvar_RegisterVariable (&gl_fogstart);
4312                 Cvar_RegisterVariable (&gl_fogend);
4313                 Cvar_RegisterVariable (&gl_skyclip);
4314         }
4315         Cvar_RegisterVariable(&r_motionblur);
4316         Cvar_RegisterVariable(&r_damageblur);
4317         Cvar_RegisterVariable(&r_motionblur_averaging);
4318         Cvar_RegisterVariable(&r_motionblur_randomize);
4319         Cvar_RegisterVariable(&r_motionblur_minblur);
4320         Cvar_RegisterVariable(&r_motionblur_maxblur);
4321         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4322         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4323         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4324         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4325         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4326         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4327         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4328         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4329         Cvar_RegisterVariable(&r_equalize_entities_by);
4330         Cvar_RegisterVariable(&r_equalize_entities_to);
4331         Cvar_RegisterVariable(&r_depthfirst);
4332         Cvar_RegisterVariable(&r_useinfinitefarclip);
4333         Cvar_RegisterVariable(&r_farclip_base);
4334         Cvar_RegisterVariable(&r_farclip_world);
4335         Cvar_RegisterVariable(&r_nearclip);
4336         Cvar_RegisterVariable(&r_deformvertexes);
4337         Cvar_RegisterVariable(&r_transparent);
4338         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4339         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4340         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4341         Cvar_RegisterVariable(&r_showoverdraw);
4342         Cvar_RegisterVariable(&r_showbboxes);
4343         Cvar_RegisterVariable(&r_showsurfaces);
4344         Cvar_RegisterVariable(&r_showtris);
4345         Cvar_RegisterVariable(&r_shownormals);
4346         Cvar_RegisterVariable(&r_showlighting);
4347         Cvar_RegisterVariable(&r_showshadowvolumes);
4348         Cvar_RegisterVariable(&r_showcollisionbrushes);
4349         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4350         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4351         Cvar_RegisterVariable(&r_showdisabledepthtest);
4352         Cvar_RegisterVariable(&r_drawportals);
4353         Cvar_RegisterVariable(&r_drawentities);
4354         Cvar_RegisterVariable(&r_draw2d);
4355         Cvar_RegisterVariable(&r_drawworld);
4356         Cvar_RegisterVariable(&r_cullentities_trace);
4357         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4358         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4359         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4360         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4361         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4362         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4363         Cvar_RegisterVariable(&r_sortentities);
4364         Cvar_RegisterVariable(&r_drawviewmodel);
4365         Cvar_RegisterVariable(&r_drawexteriormodel);
4366         Cvar_RegisterVariable(&r_speeds);
4367         Cvar_RegisterVariable(&r_fullbrights);
4368         Cvar_RegisterVariable(&r_wateralpha);
4369         Cvar_RegisterVariable(&r_dynamic);
4370         Cvar_RegisterVariable(&r_fakelight);
4371         Cvar_RegisterVariable(&r_fakelight_intensity);
4372         Cvar_RegisterVariable(&r_fullbright);
4373         Cvar_RegisterVariable(&r_shadows);
4374         Cvar_RegisterVariable(&r_shadows_darken);
4375         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4376         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4377         Cvar_RegisterVariable(&r_shadows_throwdistance);
4378         Cvar_RegisterVariable(&r_shadows_throwdirection);
4379         Cvar_RegisterVariable(&r_shadows_focus);
4380         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4381         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4382         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4383         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4384         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4385         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4386         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4387         Cvar_RegisterVariable(&r_fog_exp2);
4388         Cvar_RegisterVariable(&r_fog_clear);
4389         Cvar_RegisterVariable(&r_drawfog);
4390         Cvar_RegisterVariable(&r_transparentdepthmasking);
4391         Cvar_RegisterVariable(&r_transparent_sortmindist);
4392         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4393         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4394         Cvar_RegisterVariable(&r_texture_dds_load);
4395         Cvar_RegisterVariable(&r_texture_dds_save);
4396         Cvar_RegisterVariable(&r_textureunits);
4397         Cvar_RegisterVariable(&gl_combine);
4398         Cvar_RegisterVariable(&r_usedepthtextures);
4399         Cvar_RegisterVariable(&r_viewfbo);
4400         Cvar_RegisterVariable(&r_viewscale);
4401         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4402         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4403         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4404         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4405         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4406         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4407         Cvar_RegisterVariable(&r_glsl);
4408         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4409         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4410         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4411         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4412         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4413         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4414         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4415         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4416         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4417         Cvar_RegisterVariable(&r_glsl_postprocess);
4418         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4419         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4420         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4421         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4422         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4423         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4424         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4425         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4426         Cvar_RegisterVariable(&r_celshading);
4427         Cvar_RegisterVariable(&r_celoutlines);
4428
4429         Cvar_RegisterVariable(&r_water);
4430         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4431         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4432         Cvar_RegisterVariable(&r_water_clippingplanebias);
4433         Cvar_RegisterVariable(&r_water_refractdistort);
4434         Cvar_RegisterVariable(&r_water_reflectdistort);
4435         Cvar_RegisterVariable(&r_water_scissormode);
4436         Cvar_RegisterVariable(&r_water_lowquality);
4437         Cvar_RegisterVariable(&r_water_hideplayer);
4438         Cvar_RegisterVariable(&r_water_fbo);
4439
4440         Cvar_RegisterVariable(&r_lerpsprites);
4441         Cvar_RegisterVariable(&r_lerpmodels);
4442         Cvar_RegisterVariable(&r_lerplightstyles);
4443         Cvar_RegisterVariable(&r_waterscroll);
4444         Cvar_RegisterVariable(&r_bloom);
4445         Cvar_RegisterVariable(&r_bloom_colorscale);
4446         Cvar_RegisterVariable(&r_bloom_brighten);
4447         Cvar_RegisterVariable(&r_bloom_blur);
4448         Cvar_RegisterVariable(&r_bloom_resolution);
4449         Cvar_RegisterVariable(&r_bloom_colorexponent);
4450         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4451         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4452         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4453         Cvar_RegisterVariable(&r_hdr_glowintensity);
4454         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4455         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4456         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4457         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4458         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4459         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4460         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4461         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4462         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4463         Cvar_RegisterVariable(&developer_texturelogging);
4464         Cvar_RegisterVariable(&gl_lightmaps);
4465         Cvar_RegisterVariable(&r_test);
4466         Cvar_RegisterVariable(&r_batch_multidraw);
4467         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4468         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4469         Cvar_RegisterVariable(&r_glsl_skeletal);
4470         Cvar_RegisterVariable(&r_glsl_saturation);
4471         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4472         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4473         Cvar_RegisterVariable(&r_framedatasize);
4474         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4475                 Cvar_RegisterVariable(&r_buffermegs[i]);
4476         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4477         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4478                 Cvar_SetValue("r_fullbrights", 0);
4479 #ifdef DP_MOBILETOUCH
4480         // GLES devices have terrible depth precision in general, so...
4481         Cvar_SetValueQuick(&r_nearclip, 4);
4482         Cvar_SetValueQuick(&r_farclip_base, 4096);
4483         Cvar_SetValueQuick(&r_farclip_world, 0);
4484         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4485 #endif
4486         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4487 }
4488
4489 void Render_Init(void)
4490 {
4491         gl_backend_init();
4492         R_Textures_Init();
4493         GL_Main_Init();
4494         Font_Init();
4495         GL_Draw_Init();
4496         R_Shadow_Init();
4497         R_Sky_Init();
4498         GL_Surf_Init();
4499         Sbar_Init();
4500         R_Particles_Init();
4501         R_Explosion_Init();
4502         R_LightningBeams_Init();
4503         Mod_RenderInit();
4504 }
4505
4506 /*
4507 ===============
4508 GL_Init
4509 ===============
4510 */
4511 #ifndef USE_GLES2
4512 extern char *ENGINE_EXTENSIONS;
4513 void GL_Init (void)
4514 {
4515         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4516         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4517         gl_version = (const char *)qglGetString(GL_VERSION);
4518         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4519
4520         if (!gl_extensions)
4521                 gl_extensions = "";
4522         if (!gl_platformextensions)
4523                 gl_platformextensions = "";
4524
4525         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4526         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4527         Con_Printf("GL_VERSION: %s\n", gl_version);
4528         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4529         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4530
4531         VID_CheckExtensions();
4532
4533         // LordHavoc: report supported extensions
4534 #ifdef CONFIG_MENU
4535         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4536 #else
4537         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4538 #endif
4539
4540         // clear to black (loading plaque will be seen over this)
4541         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4542 }
4543 #endif
4544
4545 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4546 {
4547         int i;
4548         mplane_t *p;
4549         if (r_trippy.integer)
4550                 return false;
4551         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4552         {
4553                 p = r_refdef.view.frustum + i;
4554                 switch(p->signbits)
4555                 {
4556                 default:
4557                 case 0:
4558                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4559                                 return true;
4560                         break;
4561                 case 1:
4562                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4563                                 return true;
4564                         break;
4565                 case 2:
4566                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4567                                 return true;
4568                         break;
4569                 case 3:
4570                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4571                                 return true;
4572                         break;
4573                 case 4:
4574                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4575                                 return true;
4576                         break;
4577                 case 5:
4578                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4579                                 return true;
4580                         break;
4581                 case 6:
4582                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4583                                 return true;
4584                         break;
4585                 case 7:
4586                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4587                                 return true;
4588                         break;
4589                 }
4590         }
4591         return false;
4592 }
4593
4594 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4595 {
4596         int i;
4597         const mplane_t *p;
4598         if (r_trippy.integer)
4599                 return false;
4600         for (i = 0;i < numplanes;i++)
4601         {
4602                 p = planes + i;
4603                 switch(p->signbits)
4604                 {
4605                 default:
4606                 case 0:
4607                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4608                                 return true;
4609                         break;
4610                 case 1:
4611                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4612                                 return true;
4613                         break;
4614                 case 2:
4615                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4616                                 return true;
4617                         break;
4618                 case 3:
4619                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4620                                 return true;
4621                         break;
4622                 case 4:
4623                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4624                                 return true;
4625                         break;
4626                 case 5:
4627                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4628                                 return true;
4629                         break;
4630                 case 6:
4631                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4632                                 return true;
4633                         break;
4634                 case 7:
4635                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4636                                 return true;
4637                         break;
4638                 }
4639         }
4640         return false;
4641 }
4642
4643 //==================================================================================
4644
4645 // LordHavoc: this stores temporary data used within the same frame
4646
4647 typedef struct r_framedata_mem_s
4648 {
4649         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4650         size_t size; // how much usable space
4651         size_t current; // how much space in use
4652         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4653         size_t wantedsize; // how much space was allocated
4654         unsigned char *data; // start of real data (16byte aligned)
4655 }
4656 r_framedata_mem_t;
4657
4658 static r_framedata_mem_t *r_framedata_mem;
4659
4660 void R_FrameData_Reset(void)
4661 {
4662         while (r_framedata_mem)
4663         {
4664                 r_framedata_mem_t *next = r_framedata_mem->purge;
4665                 Mem_Free(r_framedata_mem);
4666                 r_framedata_mem = next;
4667         }
4668 }
4669
4670 static void R_FrameData_Resize(qboolean mustgrow)
4671 {
4672         size_t wantedsize;
4673         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4674         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4675         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4676         {
4677                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4678                 newmem->wantedsize = wantedsize;
4679                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4680                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4681                 newmem->current = 0;
4682                 newmem->mark = 0;
4683                 newmem->purge = r_framedata_mem;
4684                 r_framedata_mem = newmem;
4685         }
4686 }
4687
4688 void R_FrameData_NewFrame(void)
4689 {
4690         R_FrameData_Resize(false);
4691         if (!r_framedata_mem)
4692                 return;
4693         // if we ran out of space on the last frame, free the old memory now
4694         while (r_framedata_mem->purge)
4695         {
4696                 // repeatedly remove the second item in the list, leaving only head
4697                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4698                 Mem_Free(r_framedata_mem->purge);
4699                 r_framedata_mem->purge = next;
4700         }
4701         // reset the current mem pointer
4702         r_framedata_mem->current = 0;
4703         r_framedata_mem->mark = 0;
4704 }
4705
4706 void *R_FrameData_Alloc(size_t size)
4707 {
4708         void *data;
4709         float newvalue;
4710
4711         // align to 16 byte boundary - the data pointer is already aligned, so we
4712         // only need to ensure the size of every allocation is also aligned
4713         size = (size + 15) & ~15;
4714
4715         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4716         {
4717                 // emergency - we ran out of space, allocate more memory
4718                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4719                 newvalue = r_framedatasize.value * 2.0f;
4720                 // upper bound based on architecture - if we try to allocate more than this we could overflow, better to loop until we error out on allocation failure
4721                 if (sizeof(size_t) >= 8)
4722                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4723                 else
4724                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4725                 // this might not be a growing it, but we'll allocate another buffer every time
4726                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4727                 R_FrameData_Resize(true);
4728         }
4729
4730         data = r_framedata_mem->data + r_framedata_mem->current;
4731         r_framedata_mem->current += size;
4732
4733         // count the usage for stats
4734         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4735         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4736
4737         return (void *)data;
4738 }
4739
4740 void *R_FrameData_Store(size_t size, void *data)
4741 {
4742         void *d = R_FrameData_Alloc(size);
4743         if (d && data)
4744                 memcpy(d, data, size);
4745         return d;
4746 }
4747
4748 void R_FrameData_SetMark(void)
4749 {
4750         if (!r_framedata_mem)
4751                 return;
4752         r_framedata_mem->mark = r_framedata_mem->current;
4753 }
4754
4755 void R_FrameData_ReturnToMark(void)
4756 {
4757         if (!r_framedata_mem)
4758                 return;
4759         r_framedata_mem->current = r_framedata_mem->mark;
4760 }
4761
4762 //==================================================================================
4763
4764 // avoid reusing the same buffer objects on consecutive frames
4765 #define R_BUFFERDATA_CYCLE 3
4766
4767 typedef struct r_bufferdata_buffer_s
4768 {
4769         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4770         size_t size; // how much usable space
4771         size_t current; // how much space in use
4772         r_meshbuffer_t *buffer; // the buffer itself
4773 }
4774 r_bufferdata_buffer_t;
4775
4776 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4777 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4778
4779 /// frees all dynamic buffers
4780 void R_BufferData_Reset(void)
4781 {
4782         int cycle, type;
4783         r_bufferdata_buffer_t **p, *mem;
4784         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4785         {
4786                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4787                 {
4788                         // free all buffers
4789                         p = &r_bufferdata_buffer[cycle][type];
4790                         while (*p)
4791                         {
4792                                 mem = *p;
4793                                 *p = (*p)->purge;
4794                                 if (mem->buffer)
4795                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4796                                 Mem_Free(mem);
4797                         }
4798                 }
4799         }
4800 }
4801
4802 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4803 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4804 {
4805         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4806         size_t size;
4807         float newvalue = r_buffermegs[type].value;
4808
4809         // increase the cvar if we have to (but only if we already have a mem)
4810         if (mustgrow && mem)
4811                 newvalue *= 2.0f;
4812         newvalue = bound(0.25f, newvalue, 256.0f);
4813         while (newvalue * 1024*1024 < minsize)
4814                 newvalue *= 2.0f;
4815
4816         // clamp the cvar to valid range
4817         newvalue = bound(0.25f, newvalue, 256.0f);
4818         if (r_buffermegs[type].value != newvalue)
4819                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4820
4821         // calculate size in bytes
4822         size = (size_t)(newvalue * 1024*1024);
4823         size = bound(131072, size, 256*1024*1024);
4824
4825         // allocate a new buffer if the size is different (purge old one later)
4826         // or if we were told we must grow the buffer
4827         if (!mem || mem->size != size || mustgrow)
4828         {
4829                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4830                 mem->size = size;
4831                 mem->current = 0;
4832                 if (type == R_BUFFERDATA_VERTEX)
4833                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4834                 else if (type == R_BUFFERDATA_INDEX16)
4835                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4836                 else if (type == R_BUFFERDATA_INDEX32)
4837                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4838                 else if (type == R_BUFFERDATA_UNIFORM)
4839                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4840                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4841                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4842         }
4843 }
4844
4845 void R_BufferData_NewFrame(void)
4846 {
4847         int type;
4848         r_bufferdata_buffer_t **p, *mem;
4849         // cycle to the next frame's buffers
4850         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4851         // if we ran out of space on the last time we used these buffers, free the old memory now
4852         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4853         {
4854                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4855                 {
4856                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4857                         // free all but the head buffer, this is how we recycle obsolete
4858                         // buffers after they are no longer in use
4859                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4860                         while (*p)
4861                         {
4862                                 mem = *p;
4863                                 *p = (*p)->purge;
4864                                 if (mem->buffer)
4865                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4866                                 Mem_Free(mem);
4867                         }
4868                         // reset the current offset
4869                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4870                 }
4871         }
4872 }
4873
4874 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4875 {
4876         r_bufferdata_buffer_t *mem;
4877         int offset = 0;
4878         int padsize;
4879
4880         *returnbufferoffset = 0;
4881
4882         // align size to a byte boundary appropriate for the buffer type, this
4883         // makes all allocations have aligned start offsets
4884         if (type == R_BUFFERDATA_UNIFORM)
4885                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4886         else
4887                 padsize = (datasize + 15) & ~15;
4888
4889         // if we ran out of space in this buffer we must allocate a new one
4890         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)
4891                 R_BufferData_Resize(type, true, padsize);
4892
4893         // if the resize did not give us enough memory, fail
4894         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)
4895                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4896
4897         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4898         offset = (int)mem->current;
4899         mem->current += padsize;
4900
4901         // upload the data to the buffer at the chosen offset
4902         if (offset == 0)
4903                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4904         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4905
4906         // count the usage for stats
4907         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4908         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4909
4910         // return the buffer offset
4911         *returnbufferoffset = offset;
4912
4913         return mem->buffer;
4914 }
4915
4916 //==================================================================================
4917
4918 // LordHavoc: animcache originally written by Echon, rewritten since then
4919
4920 /**
4921  * Animation cache prevents re-generating mesh data for an animated model
4922  * multiple times in one frame for lighting, shadowing, reflections, etc.
4923  */
4924
4925 void R_AnimCache_Free(void)
4926 {
4927 }
4928
4929 void R_AnimCache_ClearCache(void)
4930 {
4931         int i;
4932         entity_render_t *ent;
4933
4934         for (i = 0;i < r_refdef.scene.numentities;i++)
4935         {
4936                 ent = r_refdef.scene.entities[i];
4937                 ent->animcache_vertex3f = NULL;
4938                 ent->animcache_vertex3f_vertexbuffer = NULL;
4939                 ent->animcache_vertex3f_bufferoffset = 0;
4940                 ent->animcache_normal3f = NULL;
4941                 ent->animcache_normal3f_vertexbuffer = NULL;
4942                 ent->animcache_normal3f_bufferoffset = 0;
4943                 ent->animcache_svector3f = NULL;
4944                 ent->animcache_svector3f_vertexbuffer = NULL;
4945                 ent->animcache_svector3f_bufferoffset = 0;
4946                 ent->animcache_tvector3f = NULL;
4947                 ent->animcache_tvector3f_vertexbuffer = NULL;
4948                 ent->animcache_tvector3f_bufferoffset = 0;
4949                 ent->animcache_vertexmesh = NULL;
4950                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4951                 ent->animcache_vertexmesh_bufferoffset = 0;
4952                 ent->animcache_skeletaltransform3x4 = NULL;
4953                 ent->animcache_skeletaltransform3x4buffer = NULL;
4954                 ent->animcache_skeletaltransform3x4offset = 0;
4955                 ent->animcache_skeletaltransform3x4size = 0;
4956         }
4957 }
4958
4959 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4960 {
4961         int i;
4962
4963         // check if we need the meshbuffers
4964         if (!vid.useinterleavedarrays)
4965                 return;
4966
4967         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4968                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4969         // TODO: upload vertexbuffer?
4970         if (ent->animcache_vertexmesh)
4971         {
4972                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4973                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4974                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4975                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4976                 for (i = 0;i < numvertices;i++)
4977                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4978                 if (ent->animcache_svector3f)
4979                         for (i = 0;i < numvertices;i++)
4980                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4981                 if (ent->animcache_tvector3f)
4982                         for (i = 0;i < numvertices;i++)
4983                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4984                 if (ent->animcache_normal3f)
4985                         for (i = 0;i < numvertices;i++)
4986                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4987         }
4988 }
4989
4990 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4991 {
4992         dp_model_t *model = ent->model;
4993         int numvertices;
4994
4995         // see if this ent is worth caching
4996         if (!model || !model->Draw || !model->AnimateVertices)
4997                 return false;
4998         // nothing to cache if it contains no animations and has no skeleton
4999         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
5000                 return false;
5001         // see if it is already cached for gpuskeletal
5002         if (ent->animcache_skeletaltransform3x4)
5003                 return false;
5004         // see if it is already cached as a mesh
5005         if (ent->animcache_vertex3f)
5006         {
5007                 // check if we need to add normals or tangents
5008                 if (ent->animcache_normal3f)
5009                         wantnormals = false;
5010                 if (ent->animcache_svector3f)
5011                         wanttangents = false;
5012                 if (!wantnormals && !wanttangents)
5013                         return false;
5014         }
5015
5016         // check which kind of cache we need to generate
5017         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5018         {
5019                 // cache the skeleton so the vertex shader can use it
5020                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5021                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5022                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5023                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5024                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
5025                 // note: this can fail if the buffer is at the grow limit
5026                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5027                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5028         }
5029         else if (ent->animcache_vertex3f)
5030         {
5031                 // mesh was already cached but we may need to add normals/tangents
5032                 // (this only happens with multiple views, reflections, cameras, etc)
5033                 if (wantnormals || wanttangents)
5034                 {
5035                         numvertices = model->surfmesh.num_vertices;
5036                         if (wantnormals)
5037                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5038                         if (wanttangents)
5039                         {
5040                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5041                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5042                         }
5043                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5044                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5045                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5046                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5047                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5048                 }
5049         }
5050         else
5051         {
5052                 // generate mesh cache
5053                 numvertices = model->surfmesh.num_vertices;
5054                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5055                 if (wantnormals)
5056                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5057                 if (wanttangents)
5058                 {
5059                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5060                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5061                 }
5062                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5063                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5064                 if (wantnormals || wanttangents)
5065                 {
5066                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5067                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5068                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5069                 }
5070                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5071                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5072                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5073         }
5074         return true;
5075 }
5076
5077 void R_AnimCache_CacheVisibleEntities(void)
5078 {
5079         int i;
5080         qboolean wantnormals = true;
5081         qboolean wanttangents = !r_showsurfaces.integer;
5082
5083         switch(vid.renderpath)
5084         {
5085         case RENDERPATH_GL20:
5086         case RENDERPATH_D3D9:
5087         case RENDERPATH_D3D10:
5088         case RENDERPATH_D3D11:
5089         case RENDERPATH_GLES2:
5090                 break;
5091         case RENDERPATH_GL11:
5092         case RENDERPATH_GL13:
5093         case RENDERPATH_GLES1:
5094                 wanttangents = false;
5095                 break;
5096         case RENDERPATH_SOFT:
5097                 break;
5098         }
5099
5100         if (r_shownormals.integer)
5101                 wanttangents = wantnormals = true;
5102
5103         // TODO: thread this
5104         // NOTE: R_PrepareRTLights() also caches entities
5105
5106         for (i = 0;i < r_refdef.scene.numentities;i++)
5107                 if (r_refdef.viewcache.entityvisible[i])
5108                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5109 }
5110
5111 //==================================================================================
5112
5113 extern cvar_t r_overheadsprites_pushback;
5114
5115 static void R_View_UpdateEntityLighting (void)
5116 {
5117         int i;
5118         entity_render_t *ent;
5119         vec3_t tempdiffusenormal, avg;
5120         vec_t f, fa, fd, fdd;
5121         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5122
5123         for (i = 0;i < r_refdef.scene.numentities;i++)
5124         {
5125                 ent = r_refdef.scene.entities[i];
5126
5127                 // skip unseen models
5128                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5129                         continue;
5130
5131                 // skip bsp models
5132                 if (ent->model && ent->model == cl.worldmodel)
5133                 {
5134                         // TODO: use modellight for r_ambient settings on world?
5135                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5136                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5137                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5138                         continue;
5139                 }
5140                 
5141                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5142                 {
5143                         // aleady updated by CSQC
5144                         // TODO: force modellight on BSP models in this case?
5145                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5146                 }
5147                 else
5148                 {
5149                         // fetch the lighting from the worldmodel data
5150                         VectorClear(ent->modellight_ambient);
5151                         VectorClear(ent->modellight_diffuse);
5152                         VectorClear(tempdiffusenormal);
5153                         if (ent->flags & RENDER_LIGHT)
5154                         {
5155                                 vec3_t org;
5156                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5157
5158                                 // complete lightning for lit sprites
5159                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5160                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5161                                 {
5162                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5163                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5164                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5165                                 }
5166                                 else
5167                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5168
5169                                 if(ent->flags & RENDER_EQUALIZE)
5170                                 {
5171                                         // first fix up ambient lighting...
5172                                         if(r_equalize_entities_minambient.value > 0)
5173                                         {
5174                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5175                                                 if(fd > 0)
5176                                                 {
5177                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5178                                                         if(fa < r_equalize_entities_minambient.value * fd)
5179                                                         {
5180                                                                 // solve:
5181                                                                 //   fa'/fd' = minambient
5182                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5183                                                                 //   ...
5184                                                                 //   fa' = fd' * minambient
5185                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5186                                                                 //   ...
5187                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5188                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5189                                                                 //   ...
5190                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5191                                                                 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
5192                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5193                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5194                                                         }
5195                                                 }
5196                                         }
5197
5198                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5199                                         {
5200                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5201                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5202                                                 f = fa + 0.25 * fd;
5203                                                 if(f > 0)
5204                                                 {
5205                                                         // adjust brightness and saturation to target
5206                                                         avg[0] = avg[1] = avg[2] = fa / f;
5207                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5208                                                         avg[0] = avg[1] = avg[2] = fd / f;
5209                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5210                                                 }
5211                                         }
5212                                 }
5213                         }
5214                         else // highly rare
5215                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5216                 }
5217
5218                 // move the light direction into modelspace coordinates for lighting code
5219                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5220                 if(VectorLength2(ent->modellight_lightdir) == 0)
5221                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5222                 VectorNormalize(ent->modellight_lightdir);
5223         }
5224 }
5225
5226 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5227 {
5228         int i;
5229         vec3_t eyemins, eyemaxs;
5230         vec3_t boxmins, boxmaxs;
5231         vec3_t start;
5232         vec3_t end;
5233         dp_model_t *model = r_refdef.scene.worldmodel;
5234         static vec3_t positions[] = {
5235                 { 0.5f, 0.5f, 0.5f },
5236                 { 0.0f, 0.0f, 0.0f },
5237                 { 0.0f, 0.0f, 1.0f },
5238                 { 0.0f, 1.0f, 0.0f },
5239                 { 0.0f, 1.0f, 1.0f },
5240                 { 1.0f, 0.0f, 0.0f },
5241                 { 1.0f, 0.0f, 1.0f },
5242                 { 1.0f, 1.0f, 0.0f },
5243                 { 1.0f, 1.0f, 1.0f },
5244         };
5245
5246         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5247         if (numsamples < 0)
5248                 return true;
5249
5250         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5251         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5252                 return true;
5253
5254         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5255                 return true;
5256
5257         // expand the eye box a little
5258         eyemins[0] = eye[0] - eyejitter;
5259         eyemaxs[0] = eye[0] + eyejitter;
5260         eyemins[1] = eye[1] - eyejitter;
5261         eyemaxs[1] = eye[1] + eyejitter;
5262         eyemins[2] = eye[2] - eyejitter;
5263         eyemaxs[2] = eye[2] + eyejitter;
5264         // expand the box a little
5265         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5266         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5267         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5268         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5269         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5270         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5271
5272         // return true if eye overlaps enlarged box
5273         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5274                 return true;
5275
5276         // try specific positions in the box first - note that these can be cached
5277         if (r_cullentities_trace_entityocclusion.integer)
5278         {
5279                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5280                 {
5281                         VectorCopy(eye, start);
5282                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5283                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5284                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5285                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5286                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5287                         // not picky - if the trace ended anywhere in the box we're good
5288                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5289                                 return true;
5290                 }
5291         }
5292         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5293                 return true;
5294
5295         // try various random positions
5296         for (i = 0; i < numsamples; i++)
5297         {
5298                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5299                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5300                 if (r_cullentities_trace_entityocclusion.integer)
5301                 {
5302                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5303                         // not picky - if the trace ended anywhere in the box we're good
5304                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5305                                 return true;
5306                 }
5307                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5308                         return true;
5309         }
5310
5311         return false;
5312 }
5313
5314
5315 static void R_View_UpdateEntityVisible (void)
5316 {
5317         int i;
5318         int renderimask;
5319         int samples;
5320         entity_render_t *ent;
5321
5322         if (r_refdef.envmap || r_fb.water.hideplayer)
5323                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5324         else if (chase_active.integer || r_fb.water.renderingscene)
5325                 renderimask = RENDER_VIEWMODEL;
5326         else
5327                 renderimask = RENDER_EXTERIORMODEL;
5328         if (!r_drawviewmodel.integer)
5329                 renderimask |= RENDER_VIEWMODEL;
5330         if (!r_drawexteriormodel.integer)
5331                 renderimask |= RENDER_EXTERIORMODEL;
5332         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5333         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5334         {
5335                 // worldmodel can check visibility
5336                 for (i = 0;i < r_refdef.scene.numentities;i++)
5337                 {
5338                         ent = r_refdef.scene.entities[i];
5339                         if (!(ent->flags & renderimask))
5340                         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)))
5341                         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))
5342                                 r_refdef.viewcache.entityvisible[i] = true;
5343                 }
5344         }
5345         else
5346         {
5347                 // no worldmodel or it can't check visibility
5348                 for (i = 0;i < r_refdef.scene.numentities;i++)
5349                 {
5350                         ent = r_refdef.scene.entities[i];
5351                         if (!(ent->flags & renderimask))
5352                         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)))
5353                                 r_refdef.viewcache.entityvisible[i] = true;
5354                 }
5355         }
5356         if (r_cullentities_trace.integer)
5357         {
5358                 for (i = 0;i < r_refdef.scene.numentities;i++)
5359                 {
5360                         if (!r_refdef.viewcache.entityvisible[i])
5361                                 continue;
5362                         ent = r_refdef.scene.entities[i];
5363                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5364                         {
5365                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5366                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5367                                         ent->last_trace_visibility = realtime;
5368                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5369                                         r_refdef.viewcache.entityvisible[i] = 0;
5370                         }
5371                 }
5372         }
5373 }
5374
5375 /// only used if skyrendermasked, and normally returns false
5376 static int R_DrawBrushModelsSky (void)
5377 {
5378         int i, sky;
5379         entity_render_t *ent;
5380
5381         sky = false;
5382         for (i = 0;i < r_refdef.scene.numentities;i++)
5383         {
5384                 if (!r_refdef.viewcache.entityvisible[i])
5385                         continue;
5386                 ent = r_refdef.scene.entities[i];
5387                 if (!ent->model || !ent->model->DrawSky)
5388                         continue;
5389                 ent->model->DrawSky(ent);
5390                 sky = true;
5391         }
5392         return sky;
5393 }
5394
5395 static void R_DrawNoModel(entity_render_t *ent);
5396 static void R_DrawModels(void)
5397 {
5398         int i;
5399         entity_render_t *ent;
5400
5401         for (i = 0;i < r_refdef.scene.numentities;i++)
5402         {
5403                 if (!r_refdef.viewcache.entityvisible[i])
5404                         continue;
5405                 ent = r_refdef.scene.entities[i];
5406                 r_refdef.stats[r_stat_entities]++;
5407                 /*
5408                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5409                 {
5410                         vec3_t f, l, u, o;
5411                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5412                         Con_Printf("R_DrawModels\n");
5413                         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]);
5414                         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);
5415                         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);
5416                 }
5417                 */
5418                 if (ent->model && ent->model->Draw != NULL)
5419                         ent->model->Draw(ent);
5420                 else
5421                         R_DrawNoModel(ent);
5422         }
5423 }
5424
5425 static void R_DrawModelsDepth(void)
5426 {
5427         int i;
5428         entity_render_t *ent;
5429
5430         for (i = 0;i < r_refdef.scene.numentities;i++)
5431         {
5432                 if (!r_refdef.viewcache.entityvisible[i])
5433                         continue;
5434                 ent = r_refdef.scene.entities[i];
5435                 if (ent->model && ent->model->DrawDepth != NULL)
5436                         ent->model->DrawDepth(ent);
5437         }
5438 }
5439
5440 static void R_DrawModelsDebug(void)
5441 {
5442         int i;
5443         entity_render_t *ent;
5444
5445         for (i = 0;i < r_refdef.scene.numentities;i++)
5446         {
5447                 if (!r_refdef.viewcache.entityvisible[i])
5448                         continue;
5449                 ent = r_refdef.scene.entities[i];
5450                 if (ent->model && ent->model->DrawDebug != NULL)
5451                         ent->model->DrawDebug(ent);
5452         }
5453 }
5454
5455 static void R_DrawModelsAddWaterPlanes(void)
5456 {
5457         int i;
5458         entity_render_t *ent;
5459
5460         for (i = 0;i < r_refdef.scene.numentities;i++)
5461         {
5462                 if (!r_refdef.viewcache.entityvisible[i])
5463                         continue;
5464                 ent = r_refdef.scene.entities[i];
5465                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5466                         ent->model->DrawAddWaterPlanes(ent);
5467         }
5468 }
5469
5470 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}};
5471
5472 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5473 {
5474         if (r_hdr_irisadaptation.integer)
5475         {
5476                 vec3_t p;
5477                 vec3_t ambient;
5478                 vec3_t diffuse;
5479                 vec3_t diffusenormal;
5480                 vec3_t forward;
5481                 vec_t brightness = 0.0f;
5482                 vec_t goal;
5483                 vec_t current;
5484                 vec_t d;
5485                 int c;
5486                 VectorCopy(r_refdef.view.forward, forward);
5487                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5488                 {
5489                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5490                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5491                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5492                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5493                         d = DotProduct(forward, diffusenormal);
5494                         brightness += VectorLength(ambient);
5495                         if (d > 0)
5496                                 brightness += d * VectorLength(diffuse);
5497                 }
5498                 brightness *= 1.0f / c;
5499                 brightness += 0.00001f; // make sure it's never zero
5500                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5501                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5502                 current = r_hdr_irisadaptation_value.value;
5503                 if (current < goal)
5504                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5505                 else if (current > goal)
5506                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5507                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5508                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5509         }
5510         else if (r_hdr_irisadaptation_value.value != 1.0f)
5511                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5512 }
5513
5514 static void R_View_SetFrustum(const int *scissor)
5515 {
5516         int i;
5517         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5518         vec3_t forward, left, up, origin, v;
5519
5520         if(scissor)
5521         {
5522                 // flipped x coordinates (because x points left here)
5523                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5524                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5525
5526                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5527                 switch(vid.renderpath)
5528                 {
5529                         case RENDERPATH_D3D9:
5530                         case RENDERPATH_D3D10:
5531                         case RENDERPATH_D3D11:
5532                                 // non-flipped y coordinates
5533                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5534                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5535                                 break;
5536                         case RENDERPATH_SOFT:
5537                         case RENDERPATH_GL11:
5538                         case RENDERPATH_GL13:
5539                         case RENDERPATH_GL20:
5540                         case RENDERPATH_GLES1:
5541                         case RENDERPATH_GLES2:
5542                                 // non-flipped y coordinates
5543                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5544                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5545                                 break;
5546                 }
5547         }
5548
5549         // we can't trust r_refdef.view.forward and friends in reflected scenes
5550         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5551
5552 #if 0
5553         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5554         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5555         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5556         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5557         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5558         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5559         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5560         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5561         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5562         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5563         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5564         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5565 #endif
5566
5567 #if 0
5568         zNear = r_refdef.nearclip;
5569         nudge = 1.0 - 1.0 / (1<<23);
5570         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5571         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5572         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5573         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5574         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5575         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5576         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5577         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5578 #endif
5579
5580
5581
5582 #if 0
5583         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5584         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5585         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5586         r_refdef.view.frustum[0].dist = m[15] - m[12];
5587
5588         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5589         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5590         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5591         r_refdef.view.frustum[1].dist = m[15] + m[12];
5592
5593         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5594         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5595         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5596         r_refdef.view.frustum[2].dist = m[15] - m[13];
5597
5598         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5599         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5600         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5601         r_refdef.view.frustum[3].dist = m[15] + m[13];
5602
5603         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5604         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5605         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5606         r_refdef.view.frustum[4].dist = m[15] - m[14];
5607
5608         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5609         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5610         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5611         r_refdef.view.frustum[5].dist = m[15] + m[14];
5612 #endif
5613
5614         if (r_refdef.view.useperspective)
5615         {
5616                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5617                 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]);
5618                 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]);
5619                 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]);
5620                 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]);
5621
5622                 // then the normals from the corners relative to origin
5623                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5624                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5625                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5626                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5627
5628                 // in a NORMAL view, forward cross left == up
5629                 // in a REFLECTED view, forward cross left == down
5630                 // so our cross products above need to be adjusted for a left handed coordinate system
5631                 CrossProduct(forward, left, v);
5632                 if(DotProduct(v, up) < 0)
5633                 {
5634                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5635                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5636                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5637                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5638                 }
5639
5640                 // Leaving those out was a mistake, those were in the old code, and they
5641                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5642                 // I couldn't reproduce it after adding those normalizations. --blub
5643                 VectorNormalize(r_refdef.view.frustum[0].normal);
5644                 VectorNormalize(r_refdef.view.frustum[1].normal);
5645                 VectorNormalize(r_refdef.view.frustum[2].normal);
5646                 VectorNormalize(r_refdef.view.frustum[3].normal);
5647
5648                 // make the corners absolute
5649                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5650                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5651                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5652                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5653
5654                 // one more normal
5655                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5656
5657                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5658                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5659                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5660                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5661                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5662         }
5663         else
5664         {
5665                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5666                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5667                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5668                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5669                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5670                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5671                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5672                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5673                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5674                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5675         }
5676         r_refdef.view.numfrustumplanes = 5;
5677
5678         if (r_refdef.view.useclipplane)
5679         {
5680                 r_refdef.view.numfrustumplanes = 6;
5681                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5682         }
5683
5684         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5685                 PlaneClassify(r_refdef.view.frustum + i);
5686
5687         // LordHavoc: note to all quake engine coders, Quake had a special case
5688         // for 90 degrees which assumed a square view (wrong), so I removed it,
5689         // Quake2 has it disabled as well.
5690
5691         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5692         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5693         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5694         //PlaneClassify(&frustum[0]);
5695
5696         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5697         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5698         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5699         //PlaneClassify(&frustum[1]);
5700
5701         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5702         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5703         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5704         //PlaneClassify(&frustum[2]);
5705
5706         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5707         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5708         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5709         //PlaneClassify(&frustum[3]);
5710
5711         // nearclip plane
5712         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5713         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5714         //PlaneClassify(&frustum[4]);
5715 }
5716
5717 static void R_View_UpdateWithScissor(const int *myscissor)
5718 {
5719         R_Main_ResizeViewCache();
5720         R_View_SetFrustum(myscissor);
5721         R_View_WorldVisibility(r_refdef.view.useclipplane);
5722         R_View_UpdateEntityVisible();
5723         R_View_UpdateEntityLighting();
5724 }
5725
5726 static void R_View_Update(void)
5727 {
5728         R_Main_ResizeViewCache();
5729         R_View_SetFrustum(NULL);
5730         R_View_WorldVisibility(r_refdef.view.useclipplane);
5731         R_View_UpdateEntityVisible();
5732         R_View_UpdateEntityLighting();
5733 }
5734
5735 float viewscalefpsadjusted = 1.0f;
5736
5737 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5738 {
5739         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5740         scale = bound(0.03125f, scale, 1.0f);
5741         *outwidth = (int)ceil(width * scale);
5742         *outheight = (int)ceil(height * scale);
5743 }
5744
5745 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5746 {
5747         const float *customclipplane = NULL;
5748         float plane[4];
5749         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5750         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5751         {
5752                 // LordHavoc: couldn't figure out how to make this approach the
5753                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5754                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5755                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5756                         dist = r_refdef.view.clipplane.dist;
5757                 plane[0] = r_refdef.view.clipplane.normal[0];
5758                 plane[1] = r_refdef.view.clipplane.normal[1];
5759                 plane[2] = r_refdef.view.clipplane.normal[2];
5760                 plane[3] = -dist;
5761                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5762         }
5763
5764         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5765         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5766
5767         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5768         if (!r_refdef.view.useperspective)
5769                 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);
5770         else if (vid.stencil && r_useinfinitefarclip.integer)
5771                 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);
5772         else
5773                 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);
5774         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5775         R_SetViewport(&r_refdef.view.viewport);
5776         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5777         {
5778                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5779                 float screenplane[4];
5780                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5781                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5782                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5783                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5784                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5785         }
5786 }
5787
5788 void R_EntityMatrix(const matrix4x4_t *matrix)
5789 {
5790         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5791         {
5792                 gl_modelmatrixchanged = false;
5793                 gl_modelmatrix = *matrix;
5794                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5795                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5796                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5797                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5798                 CHECKGLERROR
5799                 switch(vid.renderpath)
5800                 {
5801                 case RENDERPATH_D3D9:
5802 #ifdef SUPPORTD3D
5803                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5804                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5805 #endif
5806                         break;
5807                 case RENDERPATH_D3D10:
5808                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5809                         break;
5810                 case RENDERPATH_D3D11:
5811                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5812                         break;
5813                 case RENDERPATH_GL11:
5814                 case RENDERPATH_GL13:
5815                 case RENDERPATH_GLES1:
5816 #ifndef USE_GLES2
5817                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5818 #endif
5819                         break;
5820                 case RENDERPATH_SOFT:
5821                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5822                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5823                         break;
5824                 case RENDERPATH_GL20:
5825                 case RENDERPATH_GLES2:
5826                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5827                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5828                         break;
5829                 }
5830         }
5831 }
5832
5833 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5834 {
5835         r_viewport_t viewport;
5836
5837         CHECKGLERROR
5838
5839         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5840         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);
5841         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5842         R_SetViewport(&viewport);
5843         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5844         GL_Color(1, 1, 1, 1);
5845         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5846         GL_BlendFunc(GL_ONE, GL_ZERO);
5847         GL_ScissorTest(false);
5848         GL_DepthMask(false);
5849         GL_DepthRange(0, 1);
5850         GL_DepthTest(false);
5851         GL_DepthFunc(GL_LEQUAL);
5852         R_EntityMatrix(&identitymatrix);
5853         R_Mesh_ResetTextureState();
5854         GL_PolygonOffset(0, 0);
5855         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5856         switch(vid.renderpath)
5857         {
5858         case RENDERPATH_GL11:
5859         case RENDERPATH_GL13:
5860         case RENDERPATH_GL20:
5861         case RENDERPATH_GLES1:
5862         case RENDERPATH_GLES2:
5863                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5864                 break;
5865         case RENDERPATH_D3D9:
5866         case RENDERPATH_D3D10:
5867         case RENDERPATH_D3D11:
5868         case RENDERPATH_SOFT:
5869                 break;
5870         }
5871         GL_CullFace(GL_NONE);
5872
5873         CHECKGLERROR
5874 }
5875
5876 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5877 {
5878         DrawQ_Finish();
5879
5880         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5881 }
5882
5883 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5884 {
5885         DrawQ_Finish();
5886
5887         R_SetupView(true, fbo, depthtexture, colortexture);
5888         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5889         GL_Color(1, 1, 1, 1);
5890         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5891         GL_BlendFunc(GL_ONE, GL_ZERO);
5892         GL_ScissorTest(true);
5893         GL_DepthMask(true);
5894         GL_DepthRange(0, 1);
5895         GL_DepthTest(true);
5896         GL_DepthFunc(GL_LEQUAL);
5897         R_EntityMatrix(&identitymatrix);
5898         R_Mesh_ResetTextureState();
5899         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5900         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5901         switch(vid.renderpath)
5902         {
5903         case RENDERPATH_GL11:
5904         case RENDERPATH_GL13:
5905         case RENDERPATH_GL20:
5906         case RENDERPATH_GLES1:
5907         case RENDERPATH_GLES2:
5908                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5909                 break;
5910         case RENDERPATH_D3D9:
5911         case RENDERPATH_D3D10:
5912         case RENDERPATH_D3D11:
5913         case RENDERPATH_SOFT:
5914                 break;
5915         }
5916         GL_CullFace(r_refdef.view.cullface_back);
5917 }
5918
5919 /*
5920 ================
5921 R_RenderView_UpdateViewVectors
5922 ================
5923 */
5924 void R_RenderView_UpdateViewVectors(void)
5925 {
5926         // break apart the view matrix into vectors for various purposes
5927         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5928         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5929         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5930         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5931         // make an inverted copy of the view matrix for tracking sprites
5932         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5933 }
5934
5935 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5936 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5937
5938 static void R_Water_StartFrame(void)
5939 {
5940         int i;
5941         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5942         r_waterstate_waterplane_t *p;
5943         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;
5944
5945         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5946                 return;
5947
5948         switch(vid.renderpath)
5949         {
5950         case RENDERPATH_GL20:
5951         case RENDERPATH_D3D9:
5952         case RENDERPATH_D3D10:
5953         case RENDERPATH_D3D11:
5954         case RENDERPATH_SOFT:
5955         case RENDERPATH_GLES2:
5956                 break;
5957         case RENDERPATH_GL11:
5958         case RENDERPATH_GL13:
5959         case RENDERPATH_GLES1:
5960                 return;
5961         }
5962
5963         // set waterwidth and waterheight to the water resolution that will be
5964         // used (often less than the screen resolution for faster rendering)
5965         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5966
5967         // calculate desired texture sizes
5968         // can't use water if the card does not support the texture size
5969         if (!r_water.integer || r_showsurfaces.integer)
5970                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5971         else if (vid.support.arb_texture_non_power_of_two)
5972         {
5973                 texturewidth = waterwidth;
5974                 textureheight = waterheight;
5975                 camerawidth = waterwidth;
5976                 cameraheight = waterheight;
5977         }
5978         else
5979         {
5980                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5981                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5982                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5983                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5984         }
5985
5986         // allocate textures as needed
5987         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))
5988         {
5989                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5990                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5991                 {
5992                         if (p->texture_refraction)
5993                                 R_FreeTexture(p->texture_refraction);
5994                         p->texture_refraction = NULL;
5995                         if (p->fbo_refraction)
5996                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5997                         p->fbo_refraction = 0;
5998                         if (p->texture_reflection)
5999                                 R_FreeTexture(p->texture_reflection);
6000                         p->texture_reflection = NULL;
6001                         if (p->fbo_reflection)
6002                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
6003                         p->fbo_reflection = 0;
6004                         if (p->texture_camera)
6005                                 R_FreeTexture(p->texture_camera);
6006                         p->texture_camera = NULL;
6007                         if (p->fbo_camera)
6008                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
6009                         p->fbo_camera = 0;
6010                 }
6011                 memset(&r_fb.water, 0, sizeof(r_fb.water));
6012                 r_fb.water.texturewidth = texturewidth;
6013                 r_fb.water.textureheight = textureheight;
6014                 r_fb.water.camerawidth = camerawidth;
6015                 r_fb.water.cameraheight = cameraheight;
6016         }
6017
6018         if (r_fb.water.texturewidth)
6019         {
6020                 int scaledwidth, scaledheight;
6021
6022                 r_fb.water.enabled = true;
6023
6024                 // water resolution is usually reduced
6025                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6026                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6027                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
6028
6029                 // set up variables that will be used in shader setup
6030                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6031                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6032                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6033                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6034         }
6035
6036         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6037         r_fb.water.numwaterplanes = 0;
6038 }
6039
6040 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
6041 {
6042         int planeindex, bestplaneindex, vertexindex;
6043         vec3_t mins, maxs, normal, center, v, n;
6044         vec_t planescore, bestplanescore;
6045         mplane_t plane;
6046         r_waterstate_waterplane_t *p;
6047         texture_t *t = R_GetCurrentTexture(surface->texture);
6048
6049         rsurface.texture = t;
6050         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
6051         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
6052         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
6053                 return;
6054         // average the vertex normals, find the surface bounds (after deformvertexes)
6055         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6056         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6057         VectorCopy(n, normal);
6058         VectorCopy(v, mins);
6059         VectorCopy(v, maxs);
6060         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6061         {
6062                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6063                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6064                 VectorAdd(normal, n, normal);
6065                 mins[0] = min(mins[0], v[0]);
6066                 mins[1] = min(mins[1], v[1]);
6067                 mins[2] = min(mins[2], v[2]);
6068                 maxs[0] = max(maxs[0], v[0]);
6069                 maxs[1] = max(maxs[1], v[1]);
6070                 maxs[2] = max(maxs[2], v[2]);
6071         }
6072         VectorNormalize(normal);
6073         VectorMAM(0.5f, mins, 0.5f, maxs, center);
6074
6075         VectorCopy(normal, plane.normal);
6076         VectorNormalize(plane.normal);
6077         plane.dist = DotProduct(center, plane.normal);
6078         PlaneClassify(&plane);
6079         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6080         {
6081                 // skip backfaces (except if nocullface is set)
6082 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6083 //                      return;
6084                 VectorNegate(plane.normal, plane.normal);
6085                 plane.dist *= -1;
6086                 PlaneClassify(&plane);
6087         }
6088
6089
6090         // find a matching plane if there is one
6091         bestplaneindex = -1;
6092         bestplanescore = 1048576.0f;
6093         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6094         {
6095                 if(p->camera_entity == t->camera_entity)
6096                 {
6097                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6098                         if (bestplaneindex < 0 || bestplanescore > planescore)
6099                         {
6100                                 bestplaneindex = planeindex;
6101                                 bestplanescore = planescore;
6102                         }
6103                 }
6104         }
6105         planeindex = bestplaneindex;
6106
6107         // if this surface does not fit any known plane rendered this frame, add one
6108         if (planeindex < 0 || bestplanescore > 0.001f)
6109         {
6110                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6111                 {
6112                         // store the new plane
6113                         planeindex = r_fb.water.numwaterplanes++;
6114                         p = r_fb.water.waterplanes + planeindex;
6115                         p->plane = plane;
6116                         // clear materialflags and pvs
6117                         p->materialflags = 0;
6118                         p->pvsvalid = false;
6119                         p->camera_entity = t->camera_entity;
6120                         VectorCopy(mins, p->mins);
6121                         VectorCopy(maxs, p->maxs);
6122                 }
6123                 else
6124                 {
6125                         // We're totally screwed.
6126                         return;
6127                 }
6128         }
6129         else
6130         {
6131                 // merge mins/maxs when we're adding this surface to the plane
6132                 p = r_fb.water.waterplanes + planeindex;
6133                 p->mins[0] = min(p->mins[0], mins[0]);
6134                 p->mins[1] = min(p->mins[1], mins[1]);
6135                 p->mins[2] = min(p->mins[2], mins[2]);
6136                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6137                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6138                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6139         }
6140         // merge this surface's materialflags into the waterplane
6141         p->materialflags |= t->currentmaterialflags;
6142         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6143         {
6144                 // merge this surface's PVS into the waterplane
6145                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6146                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6147                 {
6148                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6149                         p->pvsvalid = true;
6150                 }
6151         }
6152 }
6153
6154 extern cvar_t r_drawparticles;
6155 extern cvar_t r_drawdecals;
6156
6157 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6158 {
6159         int myscissor[4];
6160         r_refdef_view_t originalview;
6161         r_refdef_view_t myview;
6162         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;
6163         r_waterstate_waterplane_t *p;
6164         vec3_t visorigin;
6165         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;
6166         char vabuf[1024];
6167
6168         originalview = r_refdef.view;
6169
6170         // lowquality hack, temporarily shut down some cvars and restore afterwards
6171         qualityreduction = r_water_lowquality.integer;
6172         if (qualityreduction > 0)
6173         {
6174                 if (qualityreduction >= 1)
6175                 {
6176                         old_r_shadows = r_shadows.integer;
6177                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6178                         old_r_dlight = r_shadow_realtime_dlight.integer;
6179                         Cvar_SetValueQuick(&r_shadows, 0);
6180                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6181                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6182                 }
6183                 if (qualityreduction >= 2)
6184                 {
6185                         old_r_dynamic = r_dynamic.integer;
6186                         old_r_particles = r_drawparticles.integer;
6187                         old_r_decals = r_drawdecals.integer;
6188                         Cvar_SetValueQuick(&r_dynamic, 0);
6189                         Cvar_SetValueQuick(&r_drawparticles, 0);
6190                         Cvar_SetValueQuick(&r_drawdecals, 0);
6191                 }
6192         }
6193
6194         // make sure enough textures are allocated
6195         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6196         {
6197                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6198                         continue;
6199                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6200                 {
6201                         if (!p->texture_refraction)
6202                                 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);
6203                         if (!p->texture_refraction)
6204                                 goto error;
6205                         if (usewaterfbo)
6206                         {
6207                                 if (r_fb.water.depthtexture == NULL)
6208                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6209                                 if (p->fbo_refraction == 0)
6210                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6211                         }
6212                 }
6213                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6214                 {
6215                         if (!p->texture_camera)
6216                                 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);
6217                         if (!p->texture_camera)
6218                                 goto error;
6219                         if (usewaterfbo)
6220                         {
6221                                 if (r_fb.water.depthtexture == NULL)
6222                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6223                                 if (p->fbo_camera == 0)
6224                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6225                         }
6226                 }
6227
6228                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6229                 {
6230                         if (!p->texture_reflection)
6231                                 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);
6232                         if (!p->texture_reflection)
6233                                 goto error;
6234                         if (usewaterfbo)
6235                         {
6236                                 if (r_fb.water.depthtexture == NULL)
6237                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6238                                 if (p->fbo_reflection == 0)
6239                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6240                         }
6241                 }
6242         }
6243
6244         // render views
6245         r_refdef.view = originalview;
6246         r_refdef.view.showdebug = false;
6247         r_refdef.view.width = r_fb.water.waterwidth;
6248         r_refdef.view.height = r_fb.water.waterheight;
6249         r_refdef.view.useclipplane = true;
6250         myview = r_refdef.view;
6251         r_fb.water.renderingscene = true;
6252         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6253         {
6254                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6255                         continue;
6256                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6257                 {
6258                         r_refdef.view = myview;
6259                         if(r_water_scissormode.integer)
6260                         {
6261                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6262                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6263                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6264                         }
6265
6266                         // render reflected scene and copy into texture
6267                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6268                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6269                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6270                         r_refdef.view.clipplane = p->plane;
6271                         // reverse the cullface settings for this render
6272                         r_refdef.view.cullface_front = GL_FRONT;
6273                         r_refdef.view.cullface_back = GL_BACK;
6274                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6275                         {
6276                                 r_refdef.view.usecustompvs = true;
6277                                 if (p->pvsvalid)
6278                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6279                                 else
6280                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6281                         }
6282
6283                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6284                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6285                         R_ClearScreen(r_refdef.fogenabled);
6286                         if(r_water_scissormode.integer & 2)
6287                                 R_View_UpdateWithScissor(myscissor);
6288                         else
6289                                 R_View_Update();
6290                         R_AnimCache_CacheVisibleEntities();
6291                         if(r_water_scissormode.integer & 1)
6292                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6293                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6294
6295                         if (!p->fbo_reflection)
6296                                 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);
6297                         r_fb.water.hideplayer = false;
6298                 }
6299
6300                 // render the normal view scene and copy into texture
6301                 // (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)
6302                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6303                 {
6304                         r_refdef.view = myview;
6305                         if(r_water_scissormode.integer)
6306                         {
6307                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6308                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6309                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6310                         }
6311
6312                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6313
6314                         r_refdef.view.clipplane = p->plane;
6315                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6316                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6317
6318                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6319                         {
6320                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6321                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6322                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6323                                 R_RenderView_UpdateViewVectors();
6324                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6325                                 {
6326                                         r_refdef.view.usecustompvs = true;
6327                                         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);
6328                                 }
6329                         }
6330
6331                         PlaneClassify(&r_refdef.view.clipplane);
6332
6333                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6334                         R_ClearScreen(r_refdef.fogenabled);
6335                         if(r_water_scissormode.integer & 2)
6336                                 R_View_UpdateWithScissor(myscissor);
6337                         else
6338                                 R_View_Update();
6339                         R_AnimCache_CacheVisibleEntities();
6340                         if(r_water_scissormode.integer & 1)
6341                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6342                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6343
6344                         if (!p->fbo_refraction)
6345                                 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);
6346                         r_fb.water.hideplayer = false;
6347                 }
6348                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6349                 {
6350                         r_refdef.view = myview;
6351
6352                         r_refdef.view.clipplane = p->plane;
6353                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6354                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6355
6356                         r_refdef.view.width = r_fb.water.camerawidth;
6357                         r_refdef.view.height = r_fb.water.cameraheight;
6358                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6359                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6360                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6361                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6362
6363                         if(p->camera_entity)
6364                         {
6365                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6366                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6367                         }
6368
6369                         // note: all of the view is used for displaying... so
6370                         // there is no use in scissoring
6371
6372                         // reverse the cullface settings for this render
6373                         r_refdef.view.cullface_front = GL_FRONT;
6374                         r_refdef.view.cullface_back = GL_BACK;
6375                         // also reverse the view matrix
6376                         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
6377                         R_RenderView_UpdateViewVectors();
6378                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6379                         {
6380                                 r_refdef.view.usecustompvs = true;
6381                                 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);
6382                         }
6383                         
6384                         // camera needs no clipplane
6385                         r_refdef.view.useclipplane = false;
6386
6387                         PlaneClassify(&r_refdef.view.clipplane);
6388
6389                         r_fb.water.hideplayer = false;
6390
6391                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6392                         R_ClearScreen(r_refdef.fogenabled);
6393                         R_View_Update();
6394                         R_AnimCache_CacheVisibleEntities();
6395                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6396
6397                         if (!p->fbo_camera)
6398                                 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);
6399                         r_fb.water.hideplayer = false;
6400                 }
6401
6402         }
6403         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6404         r_fb.water.renderingscene = false;
6405         r_refdef.view = originalview;
6406         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6407         if (!r_fb.water.depthtexture)
6408                 R_ClearScreen(r_refdef.fogenabled);
6409         R_View_Update();
6410         R_AnimCache_CacheVisibleEntities();
6411         goto finish;
6412 error:
6413         r_refdef.view = originalview;
6414         r_fb.water.renderingscene = false;
6415         Cvar_SetValueQuick(&r_water, 0);
6416         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6417 finish:
6418         // lowquality hack, restore cvars
6419         if (qualityreduction > 0)
6420         {
6421                 if (qualityreduction >= 1)
6422                 {
6423                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6424                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6425                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6426                 }
6427                 if (qualityreduction >= 2)
6428                 {
6429                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6430                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6431                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6432                 }
6433         }
6434 }
6435
6436 static void R_Bloom_StartFrame(void)
6437 {
6438         int i;
6439         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6440         int viewwidth, viewheight;
6441         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6442         textype_t textype = TEXTYPE_COLORBUFFER;
6443
6444         switch (vid.renderpath)
6445         {
6446         case RENDERPATH_GL20:
6447                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6448                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6449                 {
6450                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6451                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6452                 }
6453                 break;
6454         case RENDERPATH_GL11:
6455         case RENDERPATH_GL13:
6456         case RENDERPATH_GLES1:
6457         case RENDERPATH_GLES2:
6458         case RENDERPATH_D3D9:
6459         case RENDERPATH_D3D10:
6460         case RENDERPATH_D3D11:
6461                 r_fb.usedepthtextures = false;
6462                 break;
6463         case RENDERPATH_SOFT:
6464                 r_fb.usedepthtextures = true;
6465                 break;
6466         }
6467
6468         if (r_viewscale_fpsscaling.integer)
6469         {
6470                 double actualframetime;
6471                 double targetframetime;
6472                 double adjust;
6473                 actualframetime = r_refdef.lastdrawscreentime;
6474                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6475                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6476                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6477                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6478                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6479                 viewscalefpsadjusted += adjust;
6480                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6481         }
6482         else
6483                 viewscalefpsadjusted = 1.0f;
6484
6485         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6486
6487         switch(vid.renderpath)
6488         {
6489         case RENDERPATH_GL20:
6490         case RENDERPATH_D3D9:
6491         case RENDERPATH_D3D10:
6492         case RENDERPATH_D3D11:
6493         case RENDERPATH_SOFT:
6494         case RENDERPATH_GLES2:
6495                 break;
6496         case RENDERPATH_GL11:
6497         case RENDERPATH_GL13:
6498         case RENDERPATH_GLES1:
6499                 return;
6500         }
6501
6502         // set bloomwidth and bloomheight to the bloom resolution that will be
6503         // used (often less than the screen resolution for faster rendering)
6504         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6505         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6506         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6507         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6508         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6509
6510         // calculate desired texture sizes
6511         if (vid.support.arb_texture_non_power_of_two)
6512         {
6513                 screentexturewidth = vid.width;
6514                 screentextureheight = vid.height;
6515                 bloomtexturewidth = r_fb.bloomwidth;
6516                 bloomtextureheight = r_fb.bloomheight;
6517         }
6518         else
6519         {
6520                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6521                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6522                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6523                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6524         }
6525
6526         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))
6527         {
6528                 Cvar_SetValueQuick(&r_bloom, 0);
6529                 Cvar_SetValueQuick(&r_motionblur, 0);
6530                 Cvar_SetValueQuick(&r_damageblur, 0);
6531         }
6532
6533         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6534          && !r_bloom.integer
6535          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6536          && !useviewfbo
6537          && r_viewscale.value == 1.0f
6538          && !r_viewscale_fpsscaling.integer)
6539                 screentexturewidth = screentextureheight = 0;
6540         if (!r_bloom.integer)
6541                 bloomtexturewidth = bloomtextureheight = 0;
6542
6543         // allocate textures as needed
6544         if (r_fb.screentexturewidth != screentexturewidth
6545          || r_fb.screentextureheight != screentextureheight
6546          || r_fb.bloomtexturewidth != bloomtexturewidth
6547          || r_fb.bloomtextureheight != bloomtextureheight
6548          || r_fb.textype != textype
6549          || useviewfbo != (r_fb.fbo != 0))
6550         {
6551                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6552                 {
6553                         if (r_fb.bloomtexture[i])
6554                                 R_FreeTexture(r_fb.bloomtexture[i]);
6555                         r_fb.bloomtexture[i] = NULL;
6556
6557                         if (r_fb.bloomfbo[i])
6558                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6559                         r_fb.bloomfbo[i] = 0;
6560                 }
6561
6562                 if (r_fb.fbo)
6563                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6564                 r_fb.fbo = 0;
6565
6566                 if (r_fb.colortexture)
6567                         R_FreeTexture(r_fb.colortexture);
6568                 r_fb.colortexture = NULL;
6569
6570                 if (r_fb.depthtexture)
6571                         R_FreeTexture(r_fb.depthtexture);
6572                 r_fb.depthtexture = NULL;
6573
6574                 if (r_fb.ghosttexture)
6575                         R_FreeTexture(r_fb.ghosttexture);
6576                 r_fb.ghosttexture = NULL;
6577
6578                 r_fb.screentexturewidth = screentexturewidth;
6579                 r_fb.screentextureheight = screentextureheight;
6580                 r_fb.bloomtexturewidth = bloomtexturewidth;
6581                 r_fb.bloomtextureheight = bloomtextureheight;
6582                 r_fb.textype = textype;
6583
6584                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6585                 {
6586                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6587                                 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);
6588                         r_fb.ghosttexture_valid = false;
6589                         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);
6590                         if (useviewfbo)
6591                         {
6592                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6593                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6594                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6595                         }
6596                 }
6597
6598                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6599                 {
6600                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6601                         {
6602                                 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);
6603                                 if (useviewfbo)
6604                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6605                         }
6606                 }
6607         }
6608
6609         // bloom texture is a different resolution
6610         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6611         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6612         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6613         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6614         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6615
6616         // set up a texcoord array for the full resolution screen image
6617         // (we have to keep this around to copy back during final render)
6618         r_fb.screentexcoord2f[0] = 0;
6619         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6620         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6621         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6622         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6623         r_fb.screentexcoord2f[5] = 0;
6624         r_fb.screentexcoord2f[6] = 0;
6625         r_fb.screentexcoord2f[7] = 0;
6626
6627         if(r_fb.fbo) 
6628         {
6629                 for (i = 1;i < 8;i += 2)
6630                 {
6631                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6632                 }
6633         }
6634
6635         // set up a texcoord array for the reduced resolution bloom image
6636         // (which will be additive blended over the screen image)
6637         r_fb.bloomtexcoord2f[0] = 0;
6638         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6639         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6640         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6641         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6642         r_fb.bloomtexcoord2f[5] = 0;
6643         r_fb.bloomtexcoord2f[6] = 0;
6644         r_fb.bloomtexcoord2f[7] = 0;
6645
6646         switch(vid.renderpath)
6647         {
6648         case RENDERPATH_GL11:
6649         case RENDERPATH_GL13:
6650         case RENDERPATH_GL20:
6651         case RENDERPATH_SOFT:
6652         case RENDERPATH_GLES1:
6653         case RENDERPATH_GLES2:
6654                 break;
6655         case RENDERPATH_D3D9:
6656         case RENDERPATH_D3D10:
6657         case RENDERPATH_D3D11:
6658                 for (i = 0;i < 4;i++)
6659                 {
6660                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6661                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6662                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6663                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6664                 }
6665                 break;
6666         }
6667
6668         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6669
6670         if (r_fb.fbo)
6671                 r_refdef.view.clear = true;
6672 }
6673
6674 static void R_Bloom_MakeTexture(void)
6675 {
6676         int x, range, dir;
6677         float xoffset, yoffset, r, brighten;
6678         rtexture_t *intex;
6679         float colorscale = r_bloom_colorscale.value;
6680
6681         r_refdef.stats[r_stat_bloom]++;
6682     
6683 #if 0
6684     // this copy is unnecessary since it happens in R_BlendView already
6685         if (!r_fb.fbo)
6686         {
6687                 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);
6688                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6689         }
6690 #endif
6691
6692         // scale down screen texture to the bloom texture size
6693         CHECKGLERROR
6694         r_fb.bloomindex = 0;
6695         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6696         R_SetViewport(&r_fb.bloomviewport);
6697         GL_CullFace(GL_NONE);
6698         GL_DepthTest(false);
6699         GL_BlendFunc(GL_ONE, GL_ZERO);
6700         GL_Color(colorscale, colorscale, colorscale, 1);
6701         // 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...
6702         switch(vid.renderpath)
6703         {
6704         case RENDERPATH_GL11:
6705         case RENDERPATH_GL13:
6706         case RENDERPATH_GL20:
6707         case RENDERPATH_GLES1:
6708         case RENDERPATH_GLES2:
6709         case RENDERPATH_SOFT:
6710                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6711                 break;
6712         case RENDERPATH_D3D9:
6713         case RENDERPATH_D3D10:
6714         case RENDERPATH_D3D11:
6715                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6716                 break;
6717         }
6718         // TODO: do boxfilter scale-down in shader?
6719         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6720         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6721         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6722
6723         // we now have a properly scaled bloom image
6724         if (!r_fb.bloomfbo[r_fb.bloomindex])
6725         {
6726                 // copy it into the bloom texture
6727                 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);
6728                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6729         }
6730
6731         // multiply bloom image by itself as many times as desired
6732         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6733         {
6734                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6735                 r_fb.bloomindex ^= 1;
6736                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6737                 x *= 2;
6738                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6739                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6740                 {
6741                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6742                         GL_Color(r,r,r,1); // apply fix factor
6743                 }
6744                 else
6745                 {
6746                         if(x <= 2)
6747                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6748                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6749                         GL_Color(1,1,1,1); // no fix factor supported here
6750                 }
6751                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6752                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6753                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6754                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6755
6756                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6757                 {
6758                         // copy the darkened image to a texture
6759                         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);
6760                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6761                 }
6762         }
6763
6764         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6765         brighten = r_bloom_brighten.value;
6766         brighten = sqrt(brighten);
6767         if(range >= 1)
6768                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6769
6770         for (dir = 0;dir < 2;dir++)
6771         {
6772                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6773                 r_fb.bloomindex ^= 1;
6774                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6775                 // blend on at multiple vertical offsets to achieve a vertical blur
6776                 // TODO: do offset blends using GLSL
6777                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6778                 GL_BlendFunc(GL_ONE, GL_ZERO);
6779                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6780                 for (x = -range;x <= range;x++)
6781                 {
6782                         if (!dir){xoffset = 0;yoffset = x;}
6783                         else {xoffset = x;yoffset = 0;}
6784                         xoffset /= (float)r_fb.bloomtexturewidth;
6785                         yoffset /= (float)r_fb.bloomtextureheight;
6786                         // compute a texcoord array with the specified x and y offset
6787                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6788                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6789                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6790                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6791                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6792                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6793                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6794                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6795                         // this r value looks like a 'dot' particle, fading sharply to
6796                         // black at the edges
6797                         // (probably not realistic but looks good enough)
6798                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6799                         //r = brighten/(range*2+1);
6800                         r = brighten / (range * 2 + 1);
6801                         if(range >= 1)
6802                                 r *= (1 - x*x/(float)(range*range));
6803                         GL_Color(r, r, r, 1);
6804                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6805                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6806                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6807                         GL_BlendFunc(GL_ONE, GL_ONE);
6808                 }
6809
6810                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6811                 {
6812                         // copy the vertically or horizontally blurred bloom view to a texture
6813                         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);
6814                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6815                 }
6816         }
6817 }
6818
6819 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6820 {
6821         unsigned int permutation;
6822         float uservecs[4][4];
6823
6824         R_EntityMatrix(&identitymatrix);
6825
6826         switch (vid.renderpath)
6827         {
6828         case RENDERPATH_GL20:
6829         case RENDERPATH_D3D9:
6830         case RENDERPATH_D3D10:
6831         case RENDERPATH_D3D11:
6832         case RENDERPATH_SOFT:
6833         case RENDERPATH_GLES2:
6834                 permutation =
6835                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6836                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6837                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6838                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6839                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6840
6841                 if (r_fb.colortexture)
6842                 {
6843                         if (!r_fb.fbo)
6844                         {
6845                                 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);
6846                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6847                         }
6848
6849                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6850                         {
6851                                 // declare variables
6852                                 float blur_factor, blur_mouseaccel, blur_velocity;
6853                                 static float blur_average; 
6854                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6855
6856                                 // set a goal for the factoring
6857                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6858                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6859                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6860                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6861                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6862                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6863
6864                                 // from the goal, pick an averaged value between goal and last value
6865                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6866                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6867
6868                                 // enforce minimum amount of blur 
6869                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6870
6871                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6872
6873                                 // calculate values into a standard alpha
6874                                 cl.motionbluralpha = 1 - exp(-
6875                                                 (
6876                                                  (r_motionblur.value * blur_factor / 80)
6877                                                  +
6878                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6879                                                 )
6880                                                 /
6881                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6882                                           );
6883
6884                                 // randomization for the blur value to combat persistent ghosting
6885                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6886                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6887
6888                                 // apply the blur
6889                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6890                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6891                                 {
6892                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6893                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6894                                         switch(vid.renderpath)
6895                                         {
6896                                         case RENDERPATH_GL11:
6897                                         case RENDERPATH_GL13:
6898                                         case RENDERPATH_GL20:
6899                                         case RENDERPATH_GLES1:
6900                                         case RENDERPATH_GLES2:
6901                                         case RENDERPATH_SOFT:
6902                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6903                                                 break;
6904                                         case RENDERPATH_D3D9:
6905                                         case RENDERPATH_D3D10:
6906                                         case RENDERPATH_D3D11:
6907                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6908                                                 break;
6909                                         }
6910                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6911                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6912                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6913                                 }
6914
6915                                 // updates old view angles for next pass
6916                                 VectorCopy(cl.viewangles, blur_oldangles);
6917
6918                                 // copy view into the ghost texture
6919                                 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);
6920                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6921                                 r_fb.ghosttexture_valid = true;
6922                         }
6923                 }
6924                 else
6925                 {
6926                         // no r_fb.colortexture means we're rendering to the real fb
6927                         // we may still have to do view tint...
6928                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6929                         {
6930                                 // apply a color tint to the whole view
6931                                 R_ResetViewRendering2D(0, NULL, NULL);
6932                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6933                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6934                                 R_SetupShader_Generic_NoTexture(false, true);
6935                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6936                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6937                         }
6938                         break; // no screen processing, no bloom, skip it
6939                 }
6940
6941                 if (r_fb.bloomtexture[0])
6942                 {
6943                         // make the bloom texture
6944                         R_Bloom_MakeTexture();
6945                 }
6946
6947 #if _MSC_VER >= 1400
6948 #define sscanf sscanf_s
6949 #endif
6950                 memset(uservecs, 0, sizeof(uservecs));
6951                 if (r_glsl_postprocess_uservec1_enable.integer)
6952                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6953                 if (r_glsl_postprocess_uservec2_enable.integer)
6954                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6955                 if (r_glsl_postprocess_uservec3_enable.integer)
6956                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6957                 if (r_glsl_postprocess_uservec4_enable.integer)
6958                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6959
6960                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6961                 GL_Color(1, 1, 1, 1);
6962                 GL_BlendFunc(GL_ONE, GL_ZERO);
6963
6964                 switch(vid.renderpath)
6965                 {
6966                 case RENDERPATH_GL20:
6967                 case RENDERPATH_GLES2:
6968                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6969                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6970                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6971                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6972                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6973                         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]);
6974                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6975                         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]);
6976                         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]);
6977                         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]);
6978                         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]);
6979                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6980                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6981                         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);
6982                         break;
6983                 case RENDERPATH_D3D9:
6984 #ifdef SUPPORTD3D
6985                         // 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...
6986                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6987                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6988                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6989                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6990                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6991                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6992                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6993                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6994                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6995                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6996                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6997                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6998                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6999                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7000 #endif
7001                         break;
7002                 case RENDERPATH_D3D10:
7003                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7004                         break;
7005                 case RENDERPATH_D3D11:
7006                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7007                         break;
7008                 case RENDERPATH_SOFT:
7009                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7010                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
7011                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
7012                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
7013                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7014                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7015                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7016                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7017                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7018                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7019                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7020                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
7021                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7022                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7023                         break;
7024                 default:
7025                         break;
7026                 }
7027                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7028                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
7029                 break;
7030         case RENDERPATH_GL11:
7031         case RENDERPATH_GL13:
7032         case RENDERPATH_GLES1:
7033                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7034                 {
7035                         // apply a color tint to the whole view
7036                         R_ResetViewRendering2D(0, NULL, NULL);
7037                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7038                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
7039                         R_SetupShader_Generic_NoTexture(false, true);
7040                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7041                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7042                 }
7043                 break;
7044         }
7045 }
7046
7047 matrix4x4_t r_waterscrollmatrix;
7048
7049 void R_UpdateFog(void)
7050 {
7051         // Nehahra fog
7052         if (gamemode == GAME_NEHAHRA)
7053         {
7054                 if (gl_fogenable.integer)
7055                 {
7056                         r_refdef.oldgl_fogenable = true;
7057                         r_refdef.fog_density = gl_fogdensity.value;
7058                         r_refdef.fog_red = gl_fogred.value;
7059                         r_refdef.fog_green = gl_foggreen.value;
7060                         r_refdef.fog_blue = gl_fogblue.value;
7061                         r_refdef.fog_alpha = 1;
7062                         r_refdef.fog_start = 0;
7063                         r_refdef.fog_end = gl_skyclip.value;
7064                         r_refdef.fog_height = 1<<30;
7065                         r_refdef.fog_fadedepth = 128;
7066                 }
7067                 else if (r_refdef.oldgl_fogenable)
7068                 {
7069                         r_refdef.oldgl_fogenable = false;
7070                         r_refdef.fog_density = 0;
7071                         r_refdef.fog_red = 0;
7072                         r_refdef.fog_green = 0;
7073                         r_refdef.fog_blue = 0;
7074                         r_refdef.fog_alpha = 0;
7075                         r_refdef.fog_start = 0;
7076                         r_refdef.fog_end = 0;
7077                         r_refdef.fog_height = 1<<30;
7078                         r_refdef.fog_fadedepth = 128;
7079                 }
7080         }
7081
7082         // fog parms
7083         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7084         r_refdef.fog_start = max(0, r_refdef.fog_start);
7085         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7086
7087         if (r_refdef.fog_density && r_drawfog.integer)
7088         {
7089                 r_refdef.fogenabled = true;
7090                 // this is the point where the fog reaches 0.9986 alpha, which we
7091                 // consider a good enough cutoff point for the texture
7092                 // (0.9986 * 256 == 255.6)
7093                 if (r_fog_exp2.integer)
7094                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7095                 else
7096                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7097                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7098                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7099                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7100                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7101                         R_BuildFogHeightTexture();
7102                 // fog color was already set
7103                 // update the fog texture
7104                 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)
7105                         R_BuildFogTexture();
7106                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7107                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7108         }
7109         else
7110                 r_refdef.fogenabled = false;
7111
7112         // fog color
7113         if (r_refdef.fog_density)
7114         {
7115                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7116                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7117                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7118
7119                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7120                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7121                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7122                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7123
7124                 {
7125                         vec3_t fogvec;
7126                         VectorCopy(r_refdef.fogcolor, fogvec);
7127                         //   color.rgb *= ContrastBoost * SceneBrightness;
7128                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7129                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7130                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7131                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7132                 }
7133         }
7134 }
7135
7136 void R_UpdateVariables(void)
7137 {
7138         R_Textures_Frame();
7139
7140         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7141
7142         r_refdef.farclip = r_farclip_base.value;
7143         if (r_refdef.scene.worldmodel)
7144                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7145         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7146
7147         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7148                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7149         r_refdef.polygonfactor = 0;
7150         r_refdef.polygonoffset = 0;
7151         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7152         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7153
7154         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7155         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7156         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7157         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7158         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7159         if (FAKELIGHT_ENABLED)
7160         {
7161                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7162         }
7163         else if (r_refdef.scene.worldmodel)
7164         {
7165                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7166         }
7167         if (r_showsurfaces.integer)
7168         {
7169                 r_refdef.scene.rtworld = false;
7170                 r_refdef.scene.rtworldshadows = false;
7171                 r_refdef.scene.rtdlight = false;
7172                 r_refdef.scene.rtdlightshadows = false;
7173                 r_refdef.lightmapintensity = 0;
7174         }
7175
7176         r_gpuskeletal = false;
7177         switch(vid.renderpath)
7178         {
7179         case RENDERPATH_GL20:
7180                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7181         case RENDERPATH_D3D9:
7182         case RENDERPATH_D3D10:
7183         case RENDERPATH_D3D11:
7184         case RENDERPATH_SOFT:
7185         case RENDERPATH_GLES2:
7186                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7187                 {
7188                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7189                         {
7190                                 // build GLSL gamma texture
7191 #define RAMPWIDTH 256
7192                                 unsigned short ramp[RAMPWIDTH * 3];
7193                                 unsigned char rampbgr[RAMPWIDTH][4];
7194                                 int i;
7195
7196                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7197
7198                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7199                                 for(i = 0; i < RAMPWIDTH; ++i)
7200                                 {
7201                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7202                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7203                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7204                                         rampbgr[i][3] = 0;
7205                                 }
7206                                 if (r_texture_gammaramps)
7207                                 {
7208                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7209                                 }
7210                                 else
7211                                 {
7212                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7213                                 }
7214                         }
7215                 }
7216                 else
7217                 {
7218                         // remove GLSL gamma texture
7219                 }
7220                 break;
7221         case RENDERPATH_GL11:
7222         case RENDERPATH_GL13:
7223         case RENDERPATH_GLES1:
7224                 break;
7225         }
7226 }
7227
7228 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7229 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7230 /*
7231 ================
7232 R_SelectScene
7233 ================
7234 */
7235 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7236         if( scenetype != r_currentscenetype ) {
7237                 // store the old scenetype
7238                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7239                 r_currentscenetype = scenetype;
7240                 // move in the new scene
7241                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7242         }
7243 }
7244
7245 /*
7246 ================
7247 R_GetScenePointer
7248 ================
7249 */
7250 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7251 {
7252         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7253         if( scenetype == r_currentscenetype ) {
7254                 return &r_refdef.scene;
7255         } else {
7256                 return &r_scenes_store[ scenetype ];
7257         }
7258 }
7259
7260 static int R_SortEntities_Compare(const void *ap, const void *bp)
7261 {
7262         const entity_render_t *a = *(const entity_render_t **)ap;
7263         const entity_render_t *b = *(const entity_render_t **)bp;
7264
7265         // 1. compare model
7266         if(a->model < b->model)
7267                 return -1;
7268         if(a->model > b->model)
7269                 return +1;
7270
7271         // 2. compare skin
7272         // TODO possibly calculate the REAL skinnum here first using
7273         // skinscenes?
7274         if(a->skinnum < b->skinnum)
7275                 return -1;
7276         if(a->skinnum > b->skinnum)
7277                 return +1;
7278
7279         // everything we compared is equal
7280         return 0;
7281 }
7282 static void R_SortEntities(void)
7283 {
7284         // below or equal 2 ents, sorting never gains anything
7285         if(r_refdef.scene.numentities <= 2)
7286                 return;
7287         // sort
7288         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7289 }
7290
7291 /*
7292 ================
7293 R_RenderView
7294 ================
7295 */
7296 int dpsoftrast_test;
7297 extern cvar_t r_shadow_bouncegrid;
7298 void R_RenderView(void)
7299 {
7300         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7301         int fbo;
7302         rtexture_t *depthtexture;
7303         rtexture_t *colortexture;
7304
7305         dpsoftrast_test = r_test.integer;
7306
7307         if (r_timereport_active)
7308                 R_TimeReport("start");
7309         r_textureframe++; // used only by R_GetCurrentTexture
7310         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7311
7312         if(R_CompileShader_CheckStaticParms())
7313                 R_GLSL_Restart_f();
7314
7315         if (!r_drawentities.integer)
7316                 r_refdef.scene.numentities = 0;
7317         else if (r_sortentities.integer)
7318                 R_SortEntities();
7319
7320         R_AnimCache_ClearCache();
7321
7322         /* adjust for stereo display */
7323         if(R_Stereo_Active())
7324         {
7325                 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);
7326                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7327         }
7328
7329         if (r_refdef.view.isoverlay)
7330         {
7331                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7332                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7333                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7334                 R_TimeReport("depthclear");
7335
7336                 r_refdef.view.showdebug = false;
7337
7338                 r_fb.water.enabled = false;
7339                 r_fb.water.numwaterplanes = 0;
7340
7341                 R_RenderScene(0, NULL, NULL);
7342
7343                 r_refdef.view.matrix = originalmatrix;
7344
7345                 CHECKGLERROR
7346                 return;
7347         }
7348
7349         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7350         {
7351                 r_refdef.view.matrix = originalmatrix;
7352                 return;
7353         }
7354
7355         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7356
7357         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7358                 // in sRGB fallback, behave similar to true sRGB: convert this
7359                 // value from linear to sRGB
7360                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7361
7362         R_RenderView_UpdateViewVectors();
7363
7364         R_Shadow_UpdateWorldLightSelection();
7365
7366         R_Bloom_StartFrame();
7367
7368         // apply bloom brightness offset
7369         if(r_fb.bloomtexture[0])
7370                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7371
7372         R_Water_StartFrame();
7373
7374         // now we probably have an fbo to render into
7375         fbo = r_fb.fbo;
7376         depthtexture = r_fb.depthtexture;
7377         colortexture = r_fb.colortexture;
7378
7379         CHECKGLERROR
7380         if (r_timereport_active)
7381                 R_TimeReport("viewsetup");
7382
7383         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7384
7385         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7386         {
7387                 R_ClearScreen(r_refdef.fogenabled);
7388                 if (r_timereport_active)
7389                         R_TimeReport("viewclear");
7390         }
7391         r_refdef.view.clear = true;
7392
7393         r_refdef.view.showdebug = true;
7394
7395         R_View_Update();
7396         if (r_timereport_active)
7397                 R_TimeReport("visibility");
7398
7399         R_AnimCache_CacheVisibleEntities();
7400         if (r_timereport_active)
7401                 R_TimeReport("animcache");
7402
7403         R_Shadow_UpdateBounceGridTexture();
7404         if (r_timereport_active && r_shadow_bouncegrid.integer)
7405                 R_TimeReport("bouncegrid");
7406
7407         r_fb.water.numwaterplanes = 0;
7408         if (r_fb.water.enabled)
7409                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7410
7411         R_RenderScene(fbo, depthtexture, colortexture);
7412         r_fb.water.numwaterplanes = 0;
7413
7414         R_BlendView(fbo, depthtexture, colortexture);
7415         if (r_timereport_active)
7416                 R_TimeReport("blendview");
7417
7418         GL_Scissor(0, 0, vid.width, vid.height);
7419         GL_ScissorTest(false);
7420
7421         r_refdef.view.matrix = originalmatrix;
7422
7423         CHECKGLERROR
7424 }
7425
7426 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7427 {
7428         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7429         {
7430                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7431                 if (r_timereport_active)
7432                         R_TimeReport("waterworld");
7433         }
7434
7435         // don't let sound skip if going slow
7436         if (r_refdef.scene.extraupdate)
7437                 S_ExtraUpdate ();
7438
7439         R_DrawModelsAddWaterPlanes();
7440         if (r_timereport_active)
7441                 R_TimeReport("watermodels");
7442
7443         if (r_fb.water.numwaterplanes)
7444         {
7445                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7446                 if (r_timereport_active)
7447                         R_TimeReport("waterscenes");
7448         }
7449 }
7450
7451 extern cvar_t cl_locs_show;
7452 static void R_DrawLocs(void);
7453 static void R_DrawEntityBBoxes(void);
7454 static void R_DrawModelDecals(void);
7455 extern cvar_t cl_decals_newsystem;
7456 extern qboolean r_shadow_usingdeferredprepass;
7457 extern int r_shadow_shadowmapatlas_modelshadows_size;
7458 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7459 {
7460         qboolean shadowmapping = false;
7461
7462         if (r_timereport_active)
7463                 R_TimeReport("beginscene");
7464
7465         r_refdef.stats[r_stat_renders]++;
7466
7467         R_UpdateFog();
7468
7469         // don't let sound skip if going slow
7470         if (r_refdef.scene.extraupdate)
7471                 S_ExtraUpdate ();
7472
7473         R_MeshQueue_BeginScene();
7474
7475         R_SkyStartFrame();
7476
7477         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);
7478
7479         if (r_timereport_active)
7480                 R_TimeReport("skystartframe");
7481
7482         if (cl.csqc_vidvars.drawworld)
7483         {
7484                 // don't let sound skip if going slow
7485                 if (r_refdef.scene.extraupdate)
7486                         S_ExtraUpdate ();
7487
7488                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7489                 {
7490                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7491                         if (r_timereport_active)
7492                                 R_TimeReport("worldsky");
7493                 }
7494
7495                 if (R_DrawBrushModelsSky() && r_timereport_active)
7496                         R_TimeReport("bmodelsky");
7497
7498                 if (skyrendermasked && skyrenderlater)
7499                 {
7500                         // we have to force off the water clipping plane while rendering sky
7501                         R_SetupView(false, fbo, depthtexture, colortexture);
7502                         R_Sky();
7503                         R_SetupView(true, fbo, depthtexture, colortexture);
7504                         if (r_timereport_active)
7505                                 R_TimeReport("sky");
7506                 }
7507         }
7508
7509         R_Shadow_PrepareModelShadows();
7510         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7511         if (r_timereport_active)
7512                 R_TimeReport("preparelights");
7513
7514         // render all the shadowmaps that will be used for this view
7515         shadowmapping = R_Shadow_ShadowMappingEnabled();
7516         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7517         {
7518                 R_Shadow_DrawShadowMaps();
7519                 if (r_timereport_active)
7520                         R_TimeReport("shadowmaps");
7521         }
7522
7523         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7524         if (r_shadow_usingdeferredprepass)
7525                 R_Shadow_DrawPrepass();
7526
7527         // now we begin the forward pass of the view render
7528         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7529         {
7530                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7531                 if (r_timereport_active)
7532                         R_TimeReport("worlddepth");
7533         }
7534         if (r_depthfirst.integer >= 2)
7535         {
7536                 R_DrawModelsDepth();
7537                 if (r_timereport_active)
7538                         R_TimeReport("modeldepth");
7539         }
7540
7541         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7542         {
7543                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7544                 if (r_timereport_active)
7545                         R_TimeReport("world");
7546         }
7547
7548         // don't let sound skip if going slow
7549         if (r_refdef.scene.extraupdate)
7550                 S_ExtraUpdate ();
7551
7552         R_DrawModels();
7553         if (r_timereport_active)
7554                 R_TimeReport("models");
7555
7556         // don't let sound skip if going slow
7557         if (r_refdef.scene.extraupdate)
7558                 S_ExtraUpdate ();
7559
7560         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7561         {
7562                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7563                 R_Shadow_DrawModelShadows();
7564                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7565                 // don't let sound skip if going slow
7566                 if (r_refdef.scene.extraupdate)
7567                         S_ExtraUpdate ();
7568         }
7569
7570         if (!r_shadow_usingdeferredprepass)
7571         {
7572                 R_Shadow_DrawLights();
7573                 if (r_timereport_active)
7574                         R_TimeReport("rtlights");
7575         }
7576
7577         // don't let sound skip if going slow
7578         if (r_refdef.scene.extraupdate)
7579                 S_ExtraUpdate ();
7580
7581         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7582         {
7583                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7584                 R_Shadow_DrawModelShadows();
7585                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7586                 // don't let sound skip if going slow
7587                 if (r_refdef.scene.extraupdate)
7588                         S_ExtraUpdate ();
7589         }
7590
7591         if (cl.csqc_vidvars.drawworld)
7592         {
7593                 if (cl_decals_newsystem.integer)
7594                 {
7595                         R_DrawModelDecals();
7596                         if (r_timereport_active)
7597                                 R_TimeReport("modeldecals");
7598                 }
7599                 else
7600                 {
7601                         R_DrawDecals();
7602                         if (r_timereport_active)
7603                                 R_TimeReport("decals");
7604                 }
7605
7606                 R_DrawParticles();
7607                 if (r_timereport_active)
7608                         R_TimeReport("particles");
7609
7610                 R_DrawExplosions();
7611                 if (r_timereport_active)
7612                         R_TimeReport("explosions");
7613
7614                 R_DrawLightningBeams();
7615                 if (r_timereport_active)
7616                         R_TimeReport("lightning");
7617         }
7618
7619         if (cl.csqc_loaded)
7620                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7621
7622         if (r_refdef.view.showdebug)
7623         {
7624                 if (cl_locs_show.integer)
7625                 {
7626                         R_DrawLocs();
7627                         if (r_timereport_active)
7628                                 R_TimeReport("showlocs");
7629                 }
7630
7631                 if (r_drawportals.integer)
7632                 {
7633                         R_DrawPortals();
7634                         if (r_timereport_active)
7635                                 R_TimeReport("portals");
7636                 }
7637
7638                 if (r_showbboxes.value > 0)
7639                 {
7640                         R_DrawEntityBBoxes();
7641                         if (r_timereport_active)
7642                                 R_TimeReport("bboxes");
7643                 }
7644         }
7645
7646         if (r_transparent.integer)
7647         {
7648                 R_MeshQueue_RenderTransparent();
7649                 if (r_timereport_active)
7650                         R_TimeReport("drawtrans");
7651         }
7652
7653         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))
7654         {
7655                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7656                 if (r_timereport_active)
7657                         R_TimeReport("worlddebug");
7658                 R_DrawModelsDebug();
7659                 if (r_timereport_active)
7660                         R_TimeReport("modeldebug");
7661         }
7662
7663         if (cl.csqc_vidvars.drawworld)
7664         {
7665                 R_Shadow_DrawCoronas();
7666                 if (r_timereport_active)
7667                         R_TimeReport("coronas");
7668         }
7669
7670 #if 0
7671         {
7672                 GL_DepthTest(false);
7673                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7674                 GL_Color(1, 1, 1, 1);
7675                 qglBegin(GL_POLYGON);
7676                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7677                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7678                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7679                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7680                 qglEnd();
7681                 qglBegin(GL_POLYGON);
7682                 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]);
7683                 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]);
7684                 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]);
7685                 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]);
7686                 qglEnd();
7687                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7688         }
7689 #endif
7690
7691         // don't let sound skip if going slow
7692         if (r_refdef.scene.extraupdate)
7693                 S_ExtraUpdate ();
7694 }
7695
7696 static const unsigned short bboxelements[36] =
7697 {
7698         5, 1, 3, 5, 3, 7,
7699         6, 2, 0, 6, 0, 4,
7700         7, 3, 2, 7, 2, 6,
7701         4, 0, 1, 4, 1, 5,
7702         4, 5, 7, 4, 7, 6,
7703         1, 0, 2, 1, 2, 3,
7704 };
7705
7706 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7707 {
7708         int i;
7709         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7710
7711         RSurf_ActiveWorldEntity();
7712
7713         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7714         GL_DepthMask(false);
7715         GL_DepthRange(0, 1);
7716         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7717 //      R_Mesh_ResetTextureState();
7718
7719         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7720         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7721         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7722         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7723         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7724         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7725         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7726         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7727         R_FillColors(color4f, 8, cr, cg, cb, ca);
7728         if (r_refdef.fogenabled)
7729         {
7730                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7731                 {
7732                         f1 = RSurf_FogVertex(v);
7733                         f2 = 1 - f1;
7734                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7735                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7736                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7737                 }
7738         }
7739         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7740         R_Mesh_ResetTextureState();
7741         R_SetupShader_Generic_NoTexture(false, false);
7742         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7743 }
7744
7745 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7746 {
7747         prvm_prog_t *prog = SVVM_prog;
7748         int i;
7749         float color[4];
7750         prvm_edict_t *edict;
7751
7752         // this function draws bounding boxes of server entities
7753         if (!sv.active)
7754                 return;
7755
7756         GL_CullFace(GL_NONE);
7757         R_SetupShader_Generic_NoTexture(false, false);
7758
7759         for (i = 0;i < numsurfaces;i++)
7760         {
7761                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7762                 switch ((int)PRVM_serveredictfloat(edict, solid))
7763                 {
7764                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7765                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7766                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7767                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7768                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7769                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7770                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7771                 }
7772                 color[3] *= r_showbboxes.value;
7773                 color[3] = bound(0, color[3], 1);
7774                 GL_DepthTest(!r_showdisabledepthtest.integer);
7775                 GL_CullFace(r_refdef.view.cullface_front);
7776                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7777         }
7778 }
7779
7780 static void R_DrawEntityBBoxes(void)
7781 {
7782         int i;
7783         prvm_edict_t *edict;
7784         vec3_t center;
7785         prvm_prog_t *prog = SVVM_prog;
7786
7787         // this function draws bounding boxes of server entities
7788         if (!sv.active)
7789                 return;
7790
7791         for (i = 0;i < prog->num_edicts;i++)
7792         {
7793                 edict = PRVM_EDICT_NUM(i);
7794                 if (edict->priv.server->free)
7795                         continue;
7796                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7797                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7798                         continue;
7799                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7800                         continue;
7801                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7802                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7803         }
7804 }
7805
7806 static const int nomodelelement3i[24] =
7807 {
7808         5, 2, 0,
7809         5, 1, 2,
7810         5, 0, 3,
7811         5, 3, 1,
7812         0, 2, 4,
7813         2, 1, 4,
7814         3, 0, 4,
7815         1, 3, 4
7816 };
7817
7818 static const unsigned short nomodelelement3s[24] =
7819 {
7820         5, 2, 0,
7821         5, 1, 2,
7822         5, 0, 3,
7823         5, 3, 1,
7824         0, 2, 4,
7825         2, 1, 4,
7826         3, 0, 4,
7827         1, 3, 4
7828 };
7829
7830 static const float nomodelvertex3f[6*3] =
7831 {
7832         -16,   0,   0,
7833          16,   0,   0,
7834           0, -16,   0,
7835           0,  16,   0,
7836           0,   0, -16,
7837           0,   0,  16
7838 };
7839
7840 static const float nomodelcolor4f[6*4] =
7841 {
7842         0.0f, 0.0f, 0.5f, 1.0f,
7843         0.0f, 0.0f, 0.5f, 1.0f,
7844         0.0f, 0.5f, 0.0f, 1.0f,
7845         0.0f, 0.5f, 0.0f, 1.0f,
7846         0.5f, 0.0f, 0.0f, 1.0f,
7847         0.5f, 0.0f, 0.0f, 1.0f
7848 };
7849
7850 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7851 {
7852         int i;
7853         float f1, f2, *c;
7854         float color4f[6*4];
7855
7856         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);
7857
7858         // this is only called once per entity so numsurfaces is always 1, and
7859         // surfacelist is always {0}, so this code does not handle batches
7860
7861         if (rsurface.ent_flags & RENDER_ADDITIVE)
7862         {
7863                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7864                 GL_DepthMask(false);
7865         }
7866         else if (rsurface.colormod[3] < 1)
7867         {
7868                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7869                 GL_DepthMask(false);
7870         }
7871         else
7872         {
7873                 GL_BlendFunc(GL_ONE, GL_ZERO);
7874                 GL_DepthMask(true);
7875         }
7876         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7877         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7878         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7879         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7880         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7881         for (i = 0, c = color4f;i < 6;i++, c += 4)
7882         {
7883                 c[0] *= rsurface.colormod[0];
7884                 c[1] *= rsurface.colormod[1];
7885                 c[2] *= rsurface.colormod[2];
7886                 c[3] *= rsurface.colormod[3];
7887         }
7888         if (r_refdef.fogenabled)
7889         {
7890                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7891                 {
7892                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7893                         f2 = 1 - f1;
7894                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7895                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7896                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7897                 }
7898         }
7899 //      R_Mesh_ResetTextureState();
7900         R_SetupShader_Generic_NoTexture(false, false);
7901         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7902         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7903 }
7904
7905 void R_DrawNoModel(entity_render_t *ent)
7906 {
7907         vec3_t org;
7908         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7909         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7910                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7911         else
7912                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7913 }
7914
7915 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7916 {
7917         vec3_t right1, right2, diff, normal;
7918
7919         VectorSubtract (org2, org1, normal);
7920
7921         // calculate 'right' vector for start
7922         VectorSubtract (r_refdef.view.origin, org1, diff);
7923         CrossProduct (normal, diff, right1);
7924         VectorNormalize (right1);
7925
7926         // calculate 'right' vector for end
7927         VectorSubtract (r_refdef.view.origin, org2, diff);
7928         CrossProduct (normal, diff, right2);
7929         VectorNormalize (right2);
7930
7931         vert[ 0] = org1[0] + width * right1[0];
7932         vert[ 1] = org1[1] + width * right1[1];
7933         vert[ 2] = org1[2] + width * right1[2];
7934         vert[ 3] = org1[0] - width * right1[0];
7935         vert[ 4] = org1[1] - width * right1[1];
7936         vert[ 5] = org1[2] - width * right1[2];
7937         vert[ 6] = org2[0] - width * right2[0];
7938         vert[ 7] = org2[1] - width * right2[1];
7939         vert[ 8] = org2[2] - width * right2[2];
7940         vert[ 9] = org2[0] + width * right2[0];
7941         vert[10] = org2[1] + width * right2[1];
7942         vert[11] = org2[2] + width * right2[2];
7943 }
7944
7945 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)
7946 {
7947         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7948         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7949         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7950         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7951         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7952         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7953         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7954         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7955         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7956         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7957         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7958         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7959 }
7960
7961 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7962 {
7963         int i;
7964         float *vertex3f;
7965         float v[3];
7966         VectorSet(v, x, y, z);
7967         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7968                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7969                         break;
7970         if (i == mesh->numvertices)
7971         {
7972                 if (mesh->numvertices < mesh->maxvertices)
7973                 {
7974                         VectorCopy(v, vertex3f);
7975                         mesh->numvertices++;
7976                 }
7977                 return mesh->numvertices;
7978         }
7979         else
7980                 return i;
7981 }
7982
7983 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7984 {
7985         int i;
7986         int *e, element[3];
7987         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7988         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7989         e = mesh->element3i + mesh->numtriangles * 3;
7990         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7991         {
7992                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7993                 if (mesh->numtriangles < mesh->maxtriangles)
7994                 {
7995                         *e++ = element[0];
7996                         *e++ = element[1];
7997                         *e++ = element[2];
7998                         mesh->numtriangles++;
7999                 }
8000                 element[1] = element[2];
8001         }
8002 }
8003
8004 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8005 {
8006         int i;
8007         int *e, element[3];
8008         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8009         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8010         e = mesh->element3i + mesh->numtriangles * 3;
8011         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8012         {
8013                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8014                 if (mesh->numtriangles < mesh->maxtriangles)
8015                 {
8016                         *e++ = element[0];
8017                         *e++ = element[1];
8018                         *e++ = element[2];
8019                         mesh->numtriangles++;
8020                 }
8021                 element[1] = element[2];
8022         }
8023 }
8024
8025 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8026 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8027 {
8028         int planenum, planenum2;
8029         int w;
8030         int tempnumpoints;
8031         mplane_t *plane, *plane2;
8032         double maxdist;
8033         double temppoints[2][256*3];
8034         // figure out how large a bounding box we need to properly compute this brush
8035         maxdist = 0;
8036         for (w = 0;w < numplanes;w++)
8037                 maxdist = max(maxdist, fabs(planes[w].dist));
8038         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8039         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8040         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8041         {
8042                 w = 0;
8043                 tempnumpoints = 4;
8044                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8045                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8046                 {
8047                         if (planenum2 == planenum)
8048                                 continue;
8049                         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);
8050                         w = !w;
8051                 }
8052                 if (tempnumpoints < 3)
8053                         continue;
8054                 // generate elements forming a triangle fan for this polygon
8055                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8056         }
8057 }
8058
8059 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)
8060 {
8061         texturelayer_t *layer;
8062         layer = t->currentlayers + t->currentnumlayers++;
8063         layer->type = type;
8064         layer->depthmask = depthmask;
8065         layer->blendfunc1 = blendfunc1;
8066         layer->blendfunc2 = blendfunc2;
8067         layer->texture = texture;
8068         layer->texmatrix = *matrix;
8069         layer->color[0] = r;
8070         layer->color[1] = g;
8071         layer->color[2] = b;
8072         layer->color[3] = a;
8073 }
8074
8075 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8076 {
8077         if(parms[0] == 0 && parms[1] == 0)
8078                 return false;
8079         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8080                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8081                         return false;
8082         return true;
8083 }
8084
8085 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8086 {
8087         double index, f;
8088         index = parms[2] + rsurface.shadertime * parms[3];
8089         index -= floor(index);
8090         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8091         {
8092         default:
8093         case Q3WAVEFUNC_NONE:
8094         case Q3WAVEFUNC_NOISE:
8095         case Q3WAVEFUNC_COUNT:
8096                 f = 0;
8097                 break;
8098         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8099         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8100         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8101         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8102         case Q3WAVEFUNC_TRIANGLE:
8103                 index *= 4;
8104                 f = index - floor(index);
8105                 if (index < 1)
8106                 {
8107                         // f = f;
8108                 }
8109                 else if (index < 2)
8110                         f = 1 - f;
8111                 else if (index < 3)
8112                         f = -f;
8113                 else
8114                         f = -(1 - f);
8115                 break;
8116         }
8117         f = parms[0] + parms[1] * f;
8118         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8119                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8120         return (float) f;
8121 }
8122
8123 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8124 {
8125         int w, h, idx;
8126         float shadertime;
8127         float f;
8128         float offsetd[2];
8129         float tcmat[12];
8130         matrix4x4_t matrix, temp;
8131         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8132         // it's better to have one huge fixup every 9 hours than gradual
8133         // degradation over time which looks consistently bad after many hours.
8134         //
8135         // tcmod scroll in particular suffers from this degradation which can't be
8136         // effectively worked around even with floor() tricks because we don't
8137         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8138         // a workaround involving floor() would be incorrect anyway...
8139         shadertime = rsurface.shadertime;
8140         if (shadertime >= 32768.0f)
8141                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8142         switch(tcmod->tcmod)
8143         {
8144                 case Q3TCMOD_COUNT:
8145                 case Q3TCMOD_NONE:
8146                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8147                                 matrix = r_waterscrollmatrix;
8148                         else
8149                                 matrix = identitymatrix;
8150                         break;
8151                 case Q3TCMOD_ENTITYTRANSLATE:
8152                         // this is used in Q3 to allow the gamecode to control texcoord
8153                         // scrolling on the entity, which is not supported in darkplaces yet.
8154                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8155                         break;
8156                 case Q3TCMOD_ROTATE:
8157                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8158                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8159                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8160                         break;
8161                 case Q3TCMOD_SCALE:
8162                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8163                         break;
8164                 case Q3TCMOD_SCROLL:
8165                         // this particular tcmod is a "bug for bug" compatible one with regards to
8166                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8167                         // specifically did the wrapping and so we must mimic that...
8168                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8169                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8170                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8171                         break;
8172                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8173                         w = (int) tcmod->parms[0];
8174                         h = (int) tcmod->parms[1];
8175                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8176                         f = f - floor(f);
8177                         idx = (int) floor(f * w * h);
8178                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8179                         break;
8180                 case Q3TCMOD_STRETCH:
8181                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8182                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8183                         break;
8184                 case Q3TCMOD_TRANSFORM:
8185                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8186                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8187                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8188                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8189                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8190                         break;
8191                 case Q3TCMOD_TURBULENT:
8192                         // this is handled in the RSurf_PrepareVertices function
8193                         matrix = identitymatrix;
8194                         break;
8195         }
8196         temp = *texmatrix;
8197         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8198 }
8199
8200 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8201 {
8202         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8203         char name[MAX_QPATH];
8204         skinframe_t *skinframe;
8205         unsigned char pixels[296*194];
8206         strlcpy(cache->name, skinname, sizeof(cache->name));
8207         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8208         if (developer_loading.integer)
8209                 Con_Printf("loading %s\n", name);
8210         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8211         if (!skinframe || !skinframe->base)
8212         {
8213                 unsigned char *f;
8214                 fs_offset_t filesize;
8215                 skinframe = NULL;
8216                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8217                 if (f)
8218                 {
8219                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8220                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8221                         Mem_Free(f);
8222                 }
8223         }
8224         cache->skinframe = skinframe;
8225 }
8226
8227 texture_t *R_GetCurrentTexture(texture_t *t)
8228 {
8229         int i;
8230         const entity_render_t *ent = rsurface.entity;
8231         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8232         q3shaderinfo_layer_tcmod_t *tcmod;
8233
8234         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8235                 return t->currentframe;
8236         t->update_lastrenderframe = r_textureframe;
8237         t->update_lastrenderentity = (void *)ent;
8238
8239         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8240                 t->camera_entity = ent->entitynumber;
8241         else
8242                 t->camera_entity = 0;
8243
8244         // switch to an alternate material if this is a q1bsp animated material
8245         {
8246                 texture_t *texture = t;
8247                 int s = rsurface.ent_skinnum;
8248                 if ((unsigned int)s >= (unsigned int)model->numskins)
8249                         s = 0;
8250                 if (model->skinscenes)
8251                 {
8252                         if (model->skinscenes[s].framecount > 1)
8253                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8254                         else
8255                                 s = model->skinscenes[s].firstframe;
8256                 }
8257                 if (s > 0)
8258                         t = t + s * model->num_surfaces;
8259                 if (t->animated)
8260                 {
8261                         // use an alternate animation if the entity's frame is not 0,
8262                         // and only if the texture has an alternate animation
8263                         if (t->animated == 2) // q2bsp
8264                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8265                         else if (rsurface.ent_alttextures && t->anim_total[1])
8266                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8267                         else
8268                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8269                 }
8270                 texture->currentframe = t;
8271         }
8272
8273         // update currentskinframe to be a qw skin or animation frame
8274         if (rsurface.ent_qwskin >= 0)
8275         {
8276                 i = rsurface.ent_qwskin;
8277                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8278                 {
8279                         r_qwskincache_size = cl.maxclients;
8280                         if (r_qwskincache)
8281                                 Mem_Free(r_qwskincache);
8282                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8283                 }
8284                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8285                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8286                 t->currentskinframe = r_qwskincache[i].skinframe;
8287                 if (t->materialshaderpass && t->currentskinframe == NULL)
8288                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8289         }
8290         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8291                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8292         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8293                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8294
8295         t->currentmaterialflags = t->basematerialflags;
8296         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8297         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8298                 t->currentalpha *= r_wateralpha.value;
8299         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8300                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8301         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8302                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8303         if (!(rsurface.ent_flags & RENDER_LIGHT))
8304                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8305         else if (FAKELIGHT_ENABLED)
8306         {
8307                 // no modellight if using fakelight for the map
8308         }
8309         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8310         {
8311                 // pick a model lighting mode
8312                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8313                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8314                 else
8315                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8316         }
8317         if (rsurface.ent_flags & RENDER_ADDITIVE)
8318                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8319         else if (t->currentalpha < 1)
8320                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8321         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8322         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8323                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8324         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8325                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8326         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8327                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8328         if (t->backgroundshaderpass)
8329                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8330         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8331         {
8332                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8333                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8334         }
8335         else
8336                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8337         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8338         {
8339                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8340                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8341         }
8342         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8343                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8344
8345         // there is no tcmod
8346         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8347         {
8348                 t->currenttexmatrix = r_waterscrollmatrix;
8349                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8350         }
8351         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8352         {
8353                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8354                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8355         }
8356
8357         if (t->materialshaderpass)
8358                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8359                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8360
8361         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8362         if (t->currentskinframe->qpixels)
8363                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8364         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8365         if (!t->basetexture)
8366                 t->basetexture = r_texture_notexture;
8367         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8368         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8369         t->nmaptexture = t->currentskinframe->nmap;
8370         if (!t->nmaptexture)
8371                 t->nmaptexture = r_texture_blanknormalmap;
8372         t->glosstexture = r_texture_black;
8373         t->glowtexture = t->currentskinframe->glow;
8374         t->fogtexture = t->currentskinframe->fog;
8375         t->reflectmasktexture = t->currentskinframe->reflect;
8376         if (t->backgroundshaderpass)
8377         {
8378                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8379                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8380                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8381                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8382                 t->backgroundglosstexture = r_texture_black;
8383                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8384                 if (!t->backgroundnmaptexture)
8385                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8386                 // make sure that if glow is going to be used, both textures are not NULL
8387                 if (!t->backgroundglowtexture && t->glowtexture)
8388                         t->backgroundglowtexture = r_texture_black;
8389                 if (!t->glowtexture && t->backgroundglowtexture)
8390                         t->glowtexture = r_texture_black;
8391         }
8392         else
8393         {
8394                 t->backgroundbasetexture = r_texture_white;
8395                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8396                 t->backgroundglosstexture = r_texture_black;
8397                 t->backgroundglowtexture = NULL;
8398         }
8399         t->specularpower = r_shadow_glossexponent.value;
8400         // TODO: store reference values for these in the texture?
8401         t->specularscale = 0;
8402         if (r_shadow_gloss.integer > 0)
8403         {
8404                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8405                 {
8406                         if (r_shadow_glossintensity.value > 0)
8407                         {
8408                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8409                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8410                                 t->specularscale = r_shadow_glossintensity.value;
8411                         }
8412                 }
8413                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8414                 {
8415                         t->glosstexture = r_texture_white;
8416                         t->backgroundglosstexture = r_texture_white;
8417                         t->specularscale = r_shadow_gloss2intensity.value;
8418                         t->specularpower = r_shadow_gloss2exponent.value;
8419                 }
8420         }
8421         t->specularscale *= t->specularscalemod;
8422         t->specularpower *= t->specularpowermod;
8423         t->rtlightambient = 0;
8424
8425         // lightmaps mode looks bad with dlights using actual texturing, so turn
8426         // off the colormap and glossmap, but leave the normalmap on as it still
8427         // accurately represents the shading involved
8428         if (gl_lightmaps.integer)
8429         {
8430                 t->basetexture = r_texture_grey128;
8431                 t->pantstexture = r_texture_black;
8432                 t->shirttexture = r_texture_black;
8433                 if (gl_lightmaps.integer < 2)
8434                         t->nmaptexture = r_texture_blanknormalmap;
8435                 t->glosstexture = r_texture_black;
8436                 t->glowtexture = NULL;
8437                 t->fogtexture = NULL;
8438                 t->reflectmasktexture = NULL;
8439                 t->backgroundbasetexture = NULL;
8440                 if (gl_lightmaps.integer < 2)
8441                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8442                 t->backgroundglosstexture = r_texture_black;
8443                 t->backgroundglowtexture = NULL;
8444                 t->specularscale = 0;
8445                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8446         }
8447
8448         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8449         VectorClear(t->dlightcolor);
8450         t->currentnumlayers = 0;
8451         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8452         {
8453                 int blendfunc1, blendfunc2;
8454                 qboolean depthmask;
8455                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8456                 {
8457                         blendfunc1 = GL_SRC_ALPHA;
8458                         blendfunc2 = GL_ONE;
8459                 }
8460                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8461                 {
8462                         blendfunc1 = GL_SRC_ALPHA;
8463                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8464                 }
8465                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8466                 {
8467                         blendfunc1 = t->customblendfunc[0];
8468                         blendfunc2 = t->customblendfunc[1];
8469                 }
8470                 else
8471                 {
8472                         blendfunc1 = GL_ONE;
8473                         blendfunc2 = GL_ZERO;
8474                 }
8475                 // don't colormod evilblend textures
8476                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8477                         VectorSet(t->lightmapcolor, 1, 1, 1);
8478                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8479                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8480                 {
8481                         // fullbright is not affected by r_refdef.lightmapintensity
8482                         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]);
8483                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8484                                 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]);
8485                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8486                                 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]);
8487                 }
8488                 else
8489                 {
8490                         vec3_t ambientcolor;
8491                         float colorscale;
8492                         // set the color tint used for lights affecting this surface
8493                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8494                         colorscale = 2;
8495                         // q3bsp has no lightmap updates, so the lightstylevalue that
8496                         // would normally be baked into the lightmap must be
8497                         // applied to the color
8498                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8499                         if (model->type == mod_brushq3)
8500                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8501                         colorscale *= r_refdef.lightmapintensity;
8502                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8503                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8504                         // basic lit geometry
8505                         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]);
8506                         // add pants/shirt if needed
8507                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8508                                 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]);
8509                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8510                                 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]);
8511                         // now add ambient passes if needed
8512                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8513                         {
8514                                 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]);
8515                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8516                                         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]);
8517                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8518                                         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]);
8519                         }
8520                 }
8521                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8522                         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]);
8523                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8524                 {
8525                         // if this is opaque use alpha blend which will darken the earlier
8526                         // passes cheaply.
8527                         //
8528                         // if this is an alpha blended material, all the earlier passes
8529                         // were darkened by fog already, so we only need to add the fog
8530                         // color ontop through the fog mask texture
8531                         //
8532                         // if this is an additive blended material, all the earlier passes
8533                         // were darkened by fog already, and we should not add fog color
8534                         // (because the background was not darkened, there is no fog color
8535                         // that was lost behind it).
8536                         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]);
8537                 }
8538         }
8539
8540         return t;
8541 }
8542
8543 rsurfacestate_t rsurface;
8544
8545 void RSurf_ActiveWorldEntity(void)
8546 {
8547         dp_model_t *model = r_refdef.scene.worldmodel;
8548         //if (rsurface.entity == r_refdef.scene.worldentity)
8549         //      return;
8550         rsurface.entity = r_refdef.scene.worldentity;
8551         rsurface.skeleton = NULL;
8552         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8553         rsurface.ent_skinnum = 0;
8554         rsurface.ent_qwskin = -1;
8555         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8556         rsurface.shadertime = r_refdef.scene.time;
8557         rsurface.matrix = identitymatrix;
8558         rsurface.inversematrix = identitymatrix;
8559         rsurface.matrixscale = 1;
8560         rsurface.inversematrixscale = 1;
8561         R_EntityMatrix(&identitymatrix);
8562         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8563         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8564         rsurface.fograngerecip = r_refdef.fograngerecip;
8565         rsurface.fogheightfade = r_refdef.fogheightfade;
8566         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8567         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8568         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8569         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8570         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8571         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8572         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8573         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8574         rsurface.colormod[3] = 1;
8575         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);
8576         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8577         rsurface.frameblend[0].lerp = 1;
8578         rsurface.ent_alttextures = false;
8579         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8580         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8581         rsurface.entityskeletaltransform3x4 = NULL;
8582         rsurface.entityskeletaltransform3x4buffer = NULL;
8583         rsurface.entityskeletaltransform3x4offset = 0;
8584         rsurface.entityskeletaltransform3x4size = 0;;
8585         rsurface.entityskeletalnumtransforms = 0;
8586         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8587         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8588         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8589         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8590         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8591         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8592         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8593         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8594         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8595         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8596         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8597         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8598         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8599         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8600         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8601         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8602         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8603         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8604         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8605         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8606         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8607         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8608         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8609         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8610         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8611         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8612         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8613         rsurface.modelelement3i = model->surfmesh.data_element3i;
8614         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8615         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8616         rsurface.modelelement3s = model->surfmesh.data_element3s;
8617         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8618         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8619         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8620         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8621         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8622         rsurface.modelsurfaces = model->data_surfaces;
8623         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8624         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8625         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8626         rsurface.modelgeneratedvertex = false;
8627         rsurface.batchgeneratedvertex = false;
8628         rsurface.batchfirstvertex = 0;
8629         rsurface.batchnumvertices = 0;
8630         rsurface.batchfirsttriangle = 0;
8631         rsurface.batchnumtriangles = 0;
8632         rsurface.batchvertex3f  = NULL;
8633         rsurface.batchvertex3f_vertexbuffer = NULL;
8634         rsurface.batchvertex3f_bufferoffset = 0;
8635         rsurface.batchsvector3f = NULL;
8636         rsurface.batchsvector3f_vertexbuffer = NULL;
8637         rsurface.batchsvector3f_bufferoffset = 0;
8638         rsurface.batchtvector3f = NULL;
8639         rsurface.batchtvector3f_vertexbuffer = NULL;
8640         rsurface.batchtvector3f_bufferoffset = 0;
8641         rsurface.batchnormal3f  = NULL;
8642         rsurface.batchnormal3f_vertexbuffer = NULL;
8643         rsurface.batchnormal3f_bufferoffset = 0;
8644         rsurface.batchlightmapcolor4f = NULL;
8645         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8646         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8647         rsurface.batchtexcoordtexture2f = NULL;
8648         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8649         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8650         rsurface.batchtexcoordlightmap2f = NULL;
8651         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8652         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8653         rsurface.batchskeletalindex4ub = NULL;
8654         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8655         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8656         rsurface.batchskeletalweight4ub = NULL;
8657         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8658         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8659         rsurface.batchvertexmesh = NULL;
8660         rsurface.batchvertexmesh_vertexbuffer = NULL;
8661         rsurface.batchvertexmesh_bufferoffset = 0;
8662         rsurface.batchelement3i = NULL;
8663         rsurface.batchelement3i_indexbuffer = NULL;
8664         rsurface.batchelement3i_bufferoffset = 0;
8665         rsurface.batchelement3s = NULL;
8666         rsurface.batchelement3s_indexbuffer = NULL;
8667         rsurface.batchelement3s_bufferoffset = 0;
8668         rsurface.passcolor4f = NULL;
8669         rsurface.passcolor4f_vertexbuffer = NULL;
8670         rsurface.passcolor4f_bufferoffset = 0;
8671         rsurface.forcecurrenttextureupdate = false;
8672 }
8673
8674 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8675 {
8676         dp_model_t *model = ent->model;
8677         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8678         //      return;
8679         rsurface.entity = (entity_render_t *)ent;
8680         rsurface.skeleton = ent->skeleton;
8681         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8682         rsurface.ent_skinnum = ent->skinnum;
8683         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;
8684         rsurface.ent_flags = ent->flags;
8685         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8686         rsurface.matrix = ent->matrix;
8687         rsurface.inversematrix = ent->inversematrix;
8688         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8689         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8690         R_EntityMatrix(&rsurface.matrix);
8691         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8692         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8693         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8694         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8695         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8696         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8697         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8698         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8699         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8700         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8701         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8702         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8703         rsurface.colormod[3] = ent->alpha;
8704         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8705         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8706         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8707         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8708         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8709         if (ent->model->brush.submodel && !prepass)
8710         {
8711                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8712                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8713         }
8714         // if the animcache code decided it should use the shader path, skip the deform step
8715         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8716         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8717         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8718         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8719         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8720         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8721         {
8722                 if (ent->animcache_vertex3f)
8723                 {
8724                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8725                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8726                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8727                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8728                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8729                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8730                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8731                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8732                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8733                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8734                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8735                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8736                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8737                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8738                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8739                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8740                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8741                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8742                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8743                 }
8744                 else if (wanttangents)
8745                 {
8746                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8747                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8748                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8749                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8750                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8751                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8752                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8753                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8754                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8755                         rsurface.modelvertexmesh = NULL;
8756                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8757                         rsurface.modelvertexmesh_bufferoffset = 0;
8758                         rsurface.modelvertex3f_vertexbuffer = NULL;
8759                         rsurface.modelvertex3f_bufferoffset = 0;
8760                         rsurface.modelvertex3f_vertexbuffer = 0;
8761                         rsurface.modelvertex3f_bufferoffset = 0;
8762                         rsurface.modelsvector3f_vertexbuffer = 0;
8763                         rsurface.modelsvector3f_bufferoffset = 0;
8764                         rsurface.modeltvector3f_vertexbuffer = 0;
8765                         rsurface.modeltvector3f_bufferoffset = 0;
8766                         rsurface.modelnormal3f_vertexbuffer = 0;
8767                         rsurface.modelnormal3f_bufferoffset = 0;
8768                 }
8769                 else if (wantnormals)
8770                 {
8771                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8772                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8773                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8774                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8775                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8776                         rsurface.modelsvector3f = NULL;
8777                         rsurface.modeltvector3f = NULL;
8778                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8779                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8780                         rsurface.modelvertexmesh = NULL;
8781                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8782                         rsurface.modelvertexmesh_bufferoffset = 0;
8783                         rsurface.modelvertex3f_vertexbuffer = NULL;
8784                         rsurface.modelvertex3f_bufferoffset = 0;
8785                         rsurface.modelvertex3f_vertexbuffer = 0;
8786                         rsurface.modelvertex3f_bufferoffset = 0;
8787                         rsurface.modelsvector3f_vertexbuffer = 0;
8788                         rsurface.modelsvector3f_bufferoffset = 0;
8789                         rsurface.modeltvector3f_vertexbuffer = 0;
8790                         rsurface.modeltvector3f_bufferoffset = 0;
8791                         rsurface.modelnormal3f_vertexbuffer = 0;
8792                         rsurface.modelnormal3f_bufferoffset = 0;
8793                 }
8794                 else
8795                 {
8796                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8797                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8798                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8799                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8800                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8801                         rsurface.modelsvector3f = NULL;
8802                         rsurface.modeltvector3f = NULL;
8803                         rsurface.modelnormal3f = NULL;
8804                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8805                         rsurface.modelvertexmesh = NULL;
8806                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8807                         rsurface.modelvertexmesh_bufferoffset = 0;
8808                         rsurface.modelvertex3f_vertexbuffer = NULL;
8809                         rsurface.modelvertex3f_bufferoffset = 0;
8810                         rsurface.modelvertex3f_vertexbuffer = 0;
8811                         rsurface.modelvertex3f_bufferoffset = 0;
8812                         rsurface.modelsvector3f_vertexbuffer = 0;
8813                         rsurface.modelsvector3f_bufferoffset = 0;
8814                         rsurface.modeltvector3f_vertexbuffer = 0;
8815                         rsurface.modeltvector3f_bufferoffset = 0;
8816                         rsurface.modelnormal3f_vertexbuffer = 0;
8817                         rsurface.modelnormal3f_bufferoffset = 0;
8818                 }
8819                 rsurface.modelgeneratedvertex = true;
8820         }
8821         else
8822         {
8823                 if (rsurface.entityskeletaltransform3x4)
8824                 {
8825                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8826                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8827                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8828                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8829                 }
8830                 else
8831                 {
8832                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8833                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8834                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8835                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8836                 }
8837                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8838                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8839                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8840                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8841                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8842                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8843                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8844                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8845                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8846                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8847                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8848                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8849                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8850                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8851                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8852                 rsurface.modelgeneratedvertex = false;
8853         }
8854         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8855         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8856         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8857         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8858         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8859         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8860         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8861         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8862         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8863         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8864         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8865         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8866         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8867         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8868         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8869         rsurface.modelelement3i = model->surfmesh.data_element3i;
8870         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8871         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8872         rsurface.modelelement3s = model->surfmesh.data_element3s;
8873         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8874         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8875         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8876         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8877         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8878         rsurface.modelsurfaces = model->data_surfaces;
8879         rsurface.batchgeneratedvertex = false;
8880         rsurface.batchfirstvertex = 0;
8881         rsurface.batchnumvertices = 0;
8882         rsurface.batchfirsttriangle = 0;
8883         rsurface.batchnumtriangles = 0;
8884         rsurface.batchvertex3f  = NULL;
8885         rsurface.batchvertex3f_vertexbuffer = NULL;
8886         rsurface.batchvertex3f_bufferoffset = 0;
8887         rsurface.batchsvector3f = NULL;
8888         rsurface.batchsvector3f_vertexbuffer = NULL;
8889         rsurface.batchsvector3f_bufferoffset = 0;
8890         rsurface.batchtvector3f = NULL;
8891         rsurface.batchtvector3f_vertexbuffer = NULL;
8892         rsurface.batchtvector3f_bufferoffset = 0;
8893         rsurface.batchnormal3f  = NULL;
8894         rsurface.batchnormal3f_vertexbuffer = NULL;
8895         rsurface.batchnormal3f_bufferoffset = 0;
8896         rsurface.batchlightmapcolor4f = NULL;
8897         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8898         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8899         rsurface.batchtexcoordtexture2f = NULL;
8900         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8901         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8902         rsurface.batchtexcoordlightmap2f = NULL;
8903         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8904         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8905         rsurface.batchskeletalindex4ub = NULL;
8906         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8907         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8908         rsurface.batchskeletalweight4ub = NULL;
8909         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8910         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8911         rsurface.batchvertexmesh = NULL;
8912         rsurface.batchvertexmesh_vertexbuffer = NULL;
8913         rsurface.batchvertexmesh_bufferoffset = 0;
8914         rsurface.batchelement3i = NULL;
8915         rsurface.batchelement3i_indexbuffer = NULL;
8916         rsurface.batchelement3i_bufferoffset = 0;
8917         rsurface.batchelement3s = NULL;
8918         rsurface.batchelement3s_indexbuffer = NULL;
8919         rsurface.batchelement3s_bufferoffset = 0;
8920         rsurface.passcolor4f = NULL;
8921         rsurface.passcolor4f_vertexbuffer = NULL;
8922         rsurface.passcolor4f_bufferoffset = 0;
8923         rsurface.forcecurrenttextureupdate = false;
8924 }
8925
8926 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)
8927 {
8928         rsurface.entity = r_refdef.scene.worldentity;
8929         rsurface.skeleton = NULL;
8930         rsurface.ent_skinnum = 0;
8931         rsurface.ent_qwskin = -1;
8932         rsurface.ent_flags = entflags;
8933         rsurface.shadertime = r_refdef.scene.time - shadertime;
8934         rsurface.modelnumvertices = numvertices;
8935         rsurface.modelnumtriangles = numtriangles;
8936         rsurface.matrix = *matrix;
8937         rsurface.inversematrix = *inversematrix;
8938         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8939         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8940         R_EntityMatrix(&rsurface.matrix);
8941         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8942         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8943         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8944         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8945         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8946         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8947         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8948         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8949         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8950         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8951         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8952         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8953         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);
8954         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8955         rsurface.frameblend[0].lerp = 1;
8956         rsurface.ent_alttextures = false;
8957         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8958         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8959         rsurface.entityskeletaltransform3x4 = NULL;
8960         rsurface.entityskeletaltransform3x4buffer = NULL;
8961         rsurface.entityskeletaltransform3x4offset = 0;
8962         rsurface.entityskeletaltransform3x4size = 0;
8963         rsurface.entityskeletalnumtransforms = 0;
8964         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8965         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8966         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8967         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8968         if (wanttangents)
8969         {
8970                 rsurface.modelvertex3f = (float *)vertex3f;
8971                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8972                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8973                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8974         }
8975         else if (wantnormals)
8976         {
8977                 rsurface.modelvertex3f = (float *)vertex3f;
8978                 rsurface.modelsvector3f = NULL;
8979                 rsurface.modeltvector3f = NULL;
8980                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8981         }
8982         else
8983         {
8984                 rsurface.modelvertex3f = (float *)vertex3f;
8985                 rsurface.modelsvector3f = NULL;
8986                 rsurface.modeltvector3f = NULL;
8987                 rsurface.modelnormal3f = NULL;
8988         }
8989         rsurface.modelvertexmesh = NULL;
8990         rsurface.modelvertexmesh_vertexbuffer = NULL;
8991         rsurface.modelvertexmesh_bufferoffset = 0;
8992         rsurface.modelvertex3f_vertexbuffer = 0;
8993         rsurface.modelvertex3f_bufferoffset = 0;
8994         rsurface.modelsvector3f_vertexbuffer = 0;
8995         rsurface.modelsvector3f_bufferoffset = 0;
8996         rsurface.modeltvector3f_vertexbuffer = 0;
8997         rsurface.modeltvector3f_bufferoffset = 0;
8998         rsurface.modelnormal3f_vertexbuffer = 0;
8999         rsurface.modelnormal3f_bufferoffset = 0;
9000         rsurface.modelgeneratedvertex = true;
9001         rsurface.modellightmapcolor4f  = (float *)color4f;
9002         rsurface.modellightmapcolor4f_vertexbuffer = 0;
9003         rsurface.modellightmapcolor4f_bufferoffset = 0;
9004         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
9005         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9006         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9007         rsurface.modeltexcoordlightmap2f  = NULL;
9008         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9009         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9010         rsurface.modelskeletalindex4ub = NULL;
9011         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
9012         rsurface.modelskeletalindex4ub_bufferoffset = 0;
9013         rsurface.modelskeletalweight4ub = NULL;
9014         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
9015         rsurface.modelskeletalweight4ub_bufferoffset = 0;
9016         rsurface.modelelement3i = (int *)element3i;
9017         rsurface.modelelement3i_indexbuffer = NULL;
9018         rsurface.modelelement3i_bufferoffset = 0;
9019         rsurface.modelelement3s = (unsigned short *)element3s;
9020         rsurface.modelelement3s_indexbuffer = NULL;
9021         rsurface.modelelement3s_bufferoffset = 0;
9022         rsurface.modellightmapoffsets = NULL;
9023         rsurface.modelsurfaces = NULL;
9024         rsurface.batchgeneratedvertex = false;
9025         rsurface.batchfirstvertex = 0;
9026         rsurface.batchnumvertices = 0;
9027         rsurface.batchfirsttriangle = 0;
9028         rsurface.batchnumtriangles = 0;
9029         rsurface.batchvertex3f  = NULL;
9030         rsurface.batchvertex3f_vertexbuffer = NULL;
9031         rsurface.batchvertex3f_bufferoffset = 0;
9032         rsurface.batchsvector3f = NULL;
9033         rsurface.batchsvector3f_vertexbuffer = NULL;
9034         rsurface.batchsvector3f_bufferoffset = 0;
9035         rsurface.batchtvector3f = NULL;
9036         rsurface.batchtvector3f_vertexbuffer = NULL;
9037         rsurface.batchtvector3f_bufferoffset = 0;
9038         rsurface.batchnormal3f  = NULL;
9039         rsurface.batchnormal3f_vertexbuffer = NULL;
9040         rsurface.batchnormal3f_bufferoffset = 0;
9041         rsurface.batchlightmapcolor4f = NULL;
9042         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9043         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9044         rsurface.batchtexcoordtexture2f = NULL;
9045         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9046         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9047         rsurface.batchtexcoordlightmap2f = NULL;
9048         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9049         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9050         rsurface.batchskeletalindex4ub = NULL;
9051         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9052         rsurface.batchskeletalindex4ub_bufferoffset = 0;
9053         rsurface.batchskeletalweight4ub = NULL;
9054         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9055         rsurface.batchskeletalweight4ub_bufferoffset = 0;
9056         rsurface.batchvertexmesh = NULL;
9057         rsurface.batchvertexmesh_vertexbuffer = NULL;
9058         rsurface.batchvertexmesh_bufferoffset = 0;
9059         rsurface.batchelement3i = NULL;
9060         rsurface.batchelement3i_indexbuffer = NULL;
9061         rsurface.batchelement3i_bufferoffset = 0;
9062         rsurface.batchelement3s = NULL;
9063         rsurface.batchelement3s_indexbuffer = NULL;
9064         rsurface.batchelement3s_bufferoffset = 0;
9065         rsurface.passcolor4f = NULL;
9066         rsurface.passcolor4f_vertexbuffer = NULL;
9067         rsurface.passcolor4f_bufferoffset = 0;
9068         rsurface.forcecurrenttextureupdate = true;
9069
9070         if (rsurface.modelnumvertices && rsurface.modelelement3i)
9071         {
9072                 if ((wantnormals || wanttangents) && !normal3f)
9073                 {
9074                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9075                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9076                 }
9077                 if (wanttangents && !svector3f)
9078                 {
9079                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9080                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9081                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9082                 }
9083         }
9084 }
9085
9086 float RSurf_FogPoint(const float *v)
9087 {
9088         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9089         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9090         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9091         float FogHeightFade = r_refdef.fogheightfade;
9092         float fogfrac;
9093         unsigned int fogmasktableindex;
9094         if (r_refdef.fogplaneviewabove)
9095                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9096         else
9097                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9098         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9099         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9100 }
9101
9102 float RSurf_FogVertex(const float *v)
9103 {
9104         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9105         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9106         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9107         float FogHeightFade = rsurface.fogheightfade;
9108         float fogfrac;
9109         unsigned int fogmasktableindex;
9110         if (r_refdef.fogplaneviewabove)
9111                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9112         else
9113                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9114         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9115         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9116 }
9117
9118 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9119 {
9120         int i;
9121         for (i = 0;i < numelements;i++)
9122                 outelement3i[i] = inelement3i[i] + adjust;
9123 }
9124
9125 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9126 extern cvar_t gl_vbo;
9127 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9128 {
9129         int deformindex;
9130         int firsttriangle;
9131         int numtriangles;
9132         int firstvertex;
9133         int endvertex;
9134         int numvertices;
9135         int surfacefirsttriangle;
9136         int surfacenumtriangles;
9137         int surfacefirstvertex;
9138         int surfaceendvertex;
9139         int surfacenumvertices;
9140         int batchnumsurfaces = texturenumsurfaces;
9141         int batchnumvertices;
9142         int batchnumtriangles;
9143         int needsupdate;
9144         int i, j;
9145         qboolean gaps;
9146         qboolean dynamicvertex;
9147         float amplitude;
9148         float animpos;
9149         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9150         float waveparms[4];
9151         unsigned char *ub;
9152         q3shaderinfo_deform_t *deform;
9153         const msurface_t *surface, *firstsurface;
9154         r_vertexmesh_t *vertexmesh;
9155         if (!texturenumsurfaces)
9156                 return;
9157         // find vertex range of this surface batch
9158         gaps = false;
9159         firstsurface = texturesurfacelist[0];
9160         firsttriangle = firstsurface->num_firsttriangle;
9161         batchnumvertices = 0;
9162         batchnumtriangles = 0;
9163         firstvertex = endvertex = firstsurface->num_firstvertex;
9164         for (i = 0;i < texturenumsurfaces;i++)
9165         {
9166                 surface = texturesurfacelist[i];
9167                 if (surface != firstsurface + i)
9168                         gaps = true;
9169                 surfacefirstvertex = surface->num_firstvertex;
9170                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9171                 surfacenumvertices = surface->num_vertices;
9172                 surfacenumtriangles = surface->num_triangles;
9173                 if (firstvertex > surfacefirstvertex)
9174                         firstvertex = surfacefirstvertex;
9175                 if (endvertex < surfaceendvertex)
9176                         endvertex = surfaceendvertex;
9177                 batchnumvertices += surfacenumvertices;
9178                 batchnumtriangles += surfacenumtriangles;
9179         }
9180
9181         r_refdef.stats[r_stat_batch_batches]++;
9182         if (gaps)
9183                 r_refdef.stats[r_stat_batch_withgaps]++;
9184         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9185         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9186         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9187
9188         // we now know the vertex range used, and if there are any gaps in it
9189         rsurface.batchfirstvertex = firstvertex;
9190         rsurface.batchnumvertices = endvertex - firstvertex;
9191         rsurface.batchfirsttriangle = firsttriangle;
9192         rsurface.batchnumtriangles = batchnumtriangles;
9193
9194         // this variable holds flags for which properties have been updated that
9195         // may require regenerating vertexmesh array...
9196         needsupdate = 0;
9197
9198         // check if any dynamic vertex processing must occur
9199         dynamicvertex = false;
9200
9201         // a cvar to force the dynamic vertex path to be taken, for debugging
9202         if (r_batch_debugdynamicvertexpath.integer)
9203         {
9204                 if (!dynamicvertex)
9205                 {
9206                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9207                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9208                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9209                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9210                 }
9211                 dynamicvertex = true;
9212         }
9213
9214         // if there is a chance of animated vertex colors, it's a dynamic batch
9215         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9216         {
9217                 if (!dynamicvertex)
9218                 {
9219                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9220                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9221                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9222                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9223                 }
9224                 dynamicvertex = true;
9225                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9226         }
9227
9228         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9229         {
9230                 switch (deform->deform)
9231                 {
9232                 default:
9233                 case Q3DEFORM_PROJECTIONSHADOW:
9234                 case Q3DEFORM_TEXT0:
9235                 case Q3DEFORM_TEXT1:
9236                 case Q3DEFORM_TEXT2:
9237                 case Q3DEFORM_TEXT3:
9238                 case Q3DEFORM_TEXT4:
9239                 case Q3DEFORM_TEXT5:
9240                 case Q3DEFORM_TEXT6:
9241                 case Q3DEFORM_TEXT7:
9242                 case Q3DEFORM_NONE:
9243                         break;
9244                 case Q3DEFORM_AUTOSPRITE:
9245                         if (!dynamicvertex)
9246                         {
9247                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9248                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9249                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9250                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9251                         }
9252                         dynamicvertex = true;
9253                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9254                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9255                         break;
9256                 case Q3DEFORM_AUTOSPRITE2:
9257                         if (!dynamicvertex)
9258                         {
9259                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9260                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9261                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9262                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9263                         }
9264                         dynamicvertex = true;
9265                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9266                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9267                         break;
9268                 case Q3DEFORM_NORMAL:
9269                         if (!dynamicvertex)
9270                         {
9271                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9272                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9273                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9274                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9275                         }
9276                         dynamicvertex = true;
9277                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9278                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9279                         break;
9280                 case Q3DEFORM_WAVE:
9281                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9282                                 break; // if wavefunc is a nop, ignore this transform
9283                         if (!dynamicvertex)
9284                         {
9285                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9286                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9287                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9288                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9289                         }
9290                         dynamicvertex = true;
9291                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9292                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9293                         break;
9294                 case Q3DEFORM_BULGE:
9295                         if (!dynamicvertex)
9296                         {
9297                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9298                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9299                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9300                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9301                         }
9302                         dynamicvertex = true;
9303                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9304                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9305                         break;
9306                 case Q3DEFORM_MOVE:
9307                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9308                                 break; // if wavefunc is a nop, ignore this transform
9309                         if (!dynamicvertex)
9310                         {
9311                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9312                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9313                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9314                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9315                         }
9316                         dynamicvertex = true;
9317                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9318                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9319                         break;
9320                 }
9321         }
9322         if (rsurface.texture->materialshaderpass)
9323         {
9324                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9325                 {
9326                 default:
9327                 case Q3TCGEN_TEXTURE:
9328                         break;
9329                 case Q3TCGEN_LIGHTMAP:
9330                         if (!dynamicvertex)
9331                         {
9332                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9333                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9334                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9335                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9336                         }
9337                         dynamicvertex = true;
9338                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9339                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9340                         break;
9341                 case Q3TCGEN_VECTOR:
9342                         if (!dynamicvertex)
9343                         {
9344                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9345                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9346                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9347                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9348                         }
9349                         dynamicvertex = true;
9350                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9351                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9352                         break;
9353                 case Q3TCGEN_ENVIRONMENT:
9354                         if (!dynamicvertex)
9355                         {
9356                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9357                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9358                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9359                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9360                         }
9361                         dynamicvertex = true;
9362                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9363                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9364                         break;
9365                 }
9366                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9367                 {
9368                         if (!dynamicvertex)
9369                         {
9370                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9371                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9372                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9373                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9374                         }
9375                         dynamicvertex = true;
9376                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9377                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9378                 }
9379         }
9380
9381         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9382         {
9383                 if (!dynamicvertex)
9384                 {
9385                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9386                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9387                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9388                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9389                 }
9390                 dynamicvertex = true;
9391                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9392         }
9393
9394         // when the model data has no vertex buffer (dynamic mesh), we need to
9395         // eliminate gaps
9396         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9397                 batchneed |= BATCHNEED_NOGAPS;
9398
9399         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9400         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9401         // we ensure this by treating the vertex batch as dynamic...
9402         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9403         {
9404                 if (!dynamicvertex)
9405                 {
9406                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9407                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9408                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9409                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9410                 }
9411                 dynamicvertex = true;
9412         }
9413
9414         if (dynamicvertex)
9415         {
9416                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9417                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9418                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9419                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9420                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9421                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9422                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9423                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9424         }
9425
9426         // if needsupdate, we have to do a dynamic vertex batch for sure
9427         if (needsupdate & batchneed)
9428         {
9429                 if (!dynamicvertex)
9430                 {
9431                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9432                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9433                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9434                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9435                 }
9436                 dynamicvertex = true;
9437         }
9438
9439         // see if we need to build vertexmesh from arrays
9440         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9441         {
9442                 if (!dynamicvertex)
9443                 {
9444                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9445                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9446                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9447                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9448                 }
9449                 dynamicvertex = true;
9450         }
9451
9452         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9453         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9454                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9455
9456         rsurface.batchvertex3f = rsurface.modelvertex3f;
9457         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9458         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9459         rsurface.batchsvector3f = rsurface.modelsvector3f;
9460         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9461         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9462         rsurface.batchtvector3f = rsurface.modeltvector3f;
9463         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9464         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9465         rsurface.batchnormal3f = rsurface.modelnormal3f;
9466         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9467         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9468         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9469         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9470         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9471         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9472         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9473         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9474         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9475         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9476         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9477         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9478         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9479         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9480         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9481         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9482         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9483         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9484         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9485         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9486         rsurface.batchelement3i = rsurface.modelelement3i;
9487         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9488         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9489         rsurface.batchelement3s = rsurface.modelelement3s;
9490         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9491         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9492         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9493         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9494         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9495         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9496         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9497
9498         // if any dynamic vertex processing has to occur in software, we copy the
9499         // entire surface list together before processing to rebase the vertices
9500         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9501         //
9502         // if any gaps exist and we do not have a static vertex buffer, we have to
9503         // copy the surface list together to avoid wasting upload bandwidth on the
9504         // vertices in the gaps.
9505         //
9506         // if gaps exist and we have a static vertex buffer, we can choose whether
9507         // to combine the index buffer ranges into one dynamic index buffer or
9508         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9509         //
9510         // in many cases the batch is reduced to one draw call.
9511
9512         rsurface.batchmultidraw = false;
9513         rsurface.batchmultidrawnumsurfaces = 0;
9514         rsurface.batchmultidrawsurfacelist = NULL;
9515
9516         if (!dynamicvertex)
9517         {
9518                 // static vertex data, just set pointers...
9519                 rsurface.batchgeneratedvertex = false;
9520                 // if there are gaps, we want to build a combined index buffer,
9521                 // otherwise use the original static buffer with an appropriate offset
9522                 if (gaps)
9523                 {
9524                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9525                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9526                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9527                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9528                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9529                         {
9530                                 rsurface.batchmultidraw = true;
9531                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9532                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9533                                 return;
9534                         }
9535                         // build a new triangle elements array for this batch
9536                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9537                         rsurface.batchfirsttriangle = 0;
9538                         numtriangles = 0;
9539                         for (i = 0;i < texturenumsurfaces;i++)
9540                         {
9541                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9542                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9543                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9544                                 numtriangles += surfacenumtriangles;
9545                         }
9546                         rsurface.batchelement3i_indexbuffer = NULL;
9547                         rsurface.batchelement3i_bufferoffset = 0;
9548                         rsurface.batchelement3s = NULL;
9549                         rsurface.batchelement3s_indexbuffer = NULL;
9550                         rsurface.batchelement3s_bufferoffset = 0;
9551                         if (endvertex <= 65536)
9552                         {
9553                                 // make a 16bit (unsigned short) index array if possible
9554                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9555                                 for (i = 0;i < numtriangles*3;i++)
9556                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9557                         }
9558                         // upload buffer data for the copytriangles batch
9559                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9560                         {
9561                                 if (rsurface.batchelement3s)
9562                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9563                                 else if (rsurface.batchelement3i)
9564                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9565                         }
9566                 }
9567                 else
9568                 {
9569                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9570                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9571                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9572                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9573                 }
9574                 return;
9575         }
9576
9577         // something needs software processing, do it for real...
9578         // we only directly handle separate array data in this case and then
9579         // generate interleaved data if needed...
9580         rsurface.batchgeneratedvertex = true;
9581         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9582         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9583         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9584         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9585
9586         // now copy the vertex data into a combined array and make an index array
9587         // (this is what Quake3 does all the time)
9588         // we also apply any skeletal animation here that would have been done in
9589         // the vertex shader, because most of the dynamic vertex animation cases
9590         // need actual vertex positions and normals
9591         //if (dynamicvertex)
9592         {
9593                 rsurface.batchvertexmesh = NULL;
9594                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9595                 rsurface.batchvertexmesh_bufferoffset = 0;
9596                 rsurface.batchvertex3f = NULL;
9597                 rsurface.batchvertex3f_vertexbuffer = NULL;
9598                 rsurface.batchvertex3f_bufferoffset = 0;
9599                 rsurface.batchsvector3f = NULL;
9600                 rsurface.batchsvector3f_vertexbuffer = NULL;
9601                 rsurface.batchsvector3f_bufferoffset = 0;
9602                 rsurface.batchtvector3f = NULL;
9603                 rsurface.batchtvector3f_vertexbuffer = NULL;
9604                 rsurface.batchtvector3f_bufferoffset = 0;
9605                 rsurface.batchnormal3f = NULL;
9606                 rsurface.batchnormal3f_vertexbuffer = NULL;
9607                 rsurface.batchnormal3f_bufferoffset = 0;
9608                 rsurface.batchlightmapcolor4f = NULL;
9609                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9610                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9611                 rsurface.batchtexcoordtexture2f = NULL;
9612                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9613                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9614                 rsurface.batchtexcoordlightmap2f = NULL;
9615                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9616                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9617                 rsurface.batchskeletalindex4ub = NULL;
9618                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9619                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9620                 rsurface.batchskeletalweight4ub = NULL;
9621                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9622                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9623                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9624                 rsurface.batchelement3i_indexbuffer = NULL;
9625                 rsurface.batchelement3i_bufferoffset = 0;
9626                 rsurface.batchelement3s = NULL;
9627                 rsurface.batchelement3s_indexbuffer = NULL;
9628                 rsurface.batchelement3s_bufferoffset = 0;
9629                 rsurface.batchskeletaltransform3x4buffer = NULL;
9630                 rsurface.batchskeletaltransform3x4offset = 0;
9631                 rsurface.batchskeletaltransform3x4size = 0;
9632                 // we'll only be setting up certain arrays as needed
9633                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9634                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9635                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9636                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9637                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9638                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9639                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9640                 {
9641                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9642                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9643                 }
9644                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9645                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9646                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9647                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9648                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9649                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9650                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9651                 {
9652                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9653                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9654                 }
9655                 numvertices = 0;
9656                 numtriangles = 0;
9657                 for (i = 0;i < texturenumsurfaces;i++)
9658                 {
9659                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9660                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9661                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9662                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9663                         // copy only the data requested
9664                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9665                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9666                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9667                         {
9668                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9669                                 {
9670                                         if (rsurface.batchvertex3f)
9671                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9672                                         else
9673                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9674                                 }
9675                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9676                                 {
9677                                         if (rsurface.modelnormal3f)
9678                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9679                                         else
9680                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9681                                 }
9682                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9683                                 {
9684                                         if (rsurface.modelsvector3f)
9685                                         {
9686                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9687                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9688                                         }
9689                                         else
9690                                         {
9691                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9692                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9693                                         }
9694                                 }
9695                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9696                                 {
9697                                         if (rsurface.modellightmapcolor4f)
9698                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9699                                         else
9700                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9701                                 }
9702                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9703                                 {
9704                                         if (rsurface.modeltexcoordtexture2f)
9705                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9706                                         else
9707                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9708                                 }
9709                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9710                                 {
9711                                         if (rsurface.modeltexcoordlightmap2f)
9712                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9713                                         else
9714                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9715                                 }
9716                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9717                                 {
9718                                         if (rsurface.modelskeletalindex4ub)
9719                                         {
9720                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9721                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9722                                         }
9723                                         else
9724                                         {
9725                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9726                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9727                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9728                                                 for (j = 0;j < surfacenumvertices;j++)
9729                                                         ub[j*4] = 255;
9730                                         }
9731                                 }
9732                         }
9733                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9734                         numvertices += surfacenumvertices;
9735                         numtriangles += surfacenumtriangles;
9736                 }
9737
9738                 // generate a 16bit index array as well if possible
9739                 // (in general, dynamic batches fit)
9740                 if (numvertices <= 65536)
9741                 {
9742                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9743                         for (i = 0;i < numtriangles*3;i++)
9744                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9745                 }
9746
9747                 // since we've copied everything, the batch now starts at 0
9748                 rsurface.batchfirstvertex = 0;
9749                 rsurface.batchnumvertices = batchnumvertices;
9750                 rsurface.batchfirsttriangle = 0;
9751                 rsurface.batchnumtriangles = batchnumtriangles;
9752         }
9753
9754         // apply skeletal animation that would have been done in the vertex shader
9755         if (rsurface.batchskeletaltransform3x4)
9756         {
9757                 const unsigned char *si;
9758                 const unsigned char *sw;
9759                 const float *t[4];
9760                 const float *b = rsurface.batchskeletaltransform3x4;
9761                 float *vp, *vs, *vt, *vn;
9762                 float w[4];
9763                 float m[3][4], n[3][4];
9764                 float tp[3], ts[3], tt[3], tn[3];
9765                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9766                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9767                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9768                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9769                 si = rsurface.batchskeletalindex4ub;
9770                 sw = rsurface.batchskeletalweight4ub;
9771                 vp = rsurface.batchvertex3f;
9772                 vs = rsurface.batchsvector3f;
9773                 vt = rsurface.batchtvector3f;
9774                 vn = rsurface.batchnormal3f;
9775                 memset(m[0], 0, sizeof(m));
9776                 memset(n[0], 0, sizeof(n));
9777                 for (i = 0;i < batchnumvertices;i++)
9778                 {
9779                         t[0] = b + si[0]*12;
9780                         if (sw[0] == 255)
9781                         {
9782                                 // common case - only one matrix
9783                                 m[0][0] = t[0][ 0];
9784                                 m[0][1] = t[0][ 1];
9785                                 m[0][2] = t[0][ 2];
9786                                 m[0][3] = t[0][ 3];
9787                                 m[1][0] = t[0][ 4];
9788                                 m[1][1] = t[0][ 5];
9789                                 m[1][2] = t[0][ 6];
9790                                 m[1][3] = t[0][ 7];
9791                                 m[2][0] = t[0][ 8];
9792                                 m[2][1] = t[0][ 9];
9793                                 m[2][2] = t[0][10];
9794                                 m[2][3] = t[0][11];
9795                         }
9796                         else if (sw[2] + sw[3])
9797                         {
9798                                 // blend 4 matrices
9799                                 t[1] = b + si[1]*12;
9800                                 t[2] = b + si[2]*12;
9801                                 t[3] = b + si[3]*12;
9802                                 w[0] = sw[0] * (1.0f / 255.0f);
9803                                 w[1] = sw[1] * (1.0f / 255.0f);
9804                                 w[2] = sw[2] * (1.0f / 255.0f);
9805                                 w[3] = sw[3] * (1.0f / 255.0f);
9806                                 // blend the matrices
9807                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9808                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9809                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9810                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9811                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9812                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9813                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9814                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9815                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9816                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9817                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9818                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9819                         }
9820                         else
9821                         {
9822                                 // blend 2 matrices
9823                                 t[1] = b + si[1]*12;
9824                                 w[0] = sw[0] * (1.0f / 255.0f);
9825                                 w[1] = sw[1] * (1.0f / 255.0f);
9826                                 // blend the matrices
9827                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9828                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9829                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9830                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9831                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9832                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9833                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9834                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9835                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9836                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9837                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9838                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9839                         }
9840                         si += 4;
9841                         sw += 4;
9842                         // modify the vertex
9843                         VectorCopy(vp, tp);
9844                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9845                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9846                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9847                         vp += 3;
9848                         if (vn)
9849                         {
9850                                 // the normal transformation matrix is a set of cross products...
9851                                 CrossProduct(m[1], m[2], n[0]);
9852                                 CrossProduct(m[2], m[0], n[1]);
9853                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9854                                 VectorCopy(vn, tn);
9855                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9856                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9857                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9858                                 VectorNormalize(vn);
9859                                 vn += 3;
9860                                 if (vs)
9861                                 {
9862                                         VectorCopy(vs, ts);
9863                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9864                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9865                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9866                                         VectorNormalize(vs);
9867                                         vs += 3;
9868                                         VectorCopy(vt, tt);
9869                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9870                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9871                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9872                                         VectorNormalize(vt);
9873                                         vt += 3;
9874                                 }
9875                         }
9876                 }
9877                 rsurface.batchskeletaltransform3x4 = NULL;
9878                 rsurface.batchskeletalnumtransforms = 0;
9879         }
9880
9881         // q1bsp surfaces rendered in vertex color mode have to have colors
9882         // calculated based on lightstyles
9883         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9884         {
9885                 // generate color arrays for the surfaces in this list
9886                 int c[4];
9887                 int scale;
9888                 int size3;
9889                 const int *offsets;
9890                 const unsigned char *lm;
9891                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9892                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9893                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9894                 numvertices = 0;
9895                 for (i = 0;i < texturenumsurfaces;i++)
9896                 {
9897                         surface = texturesurfacelist[i];
9898                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9899                         surfacenumvertices = surface->num_vertices;
9900                         if (surface->lightmapinfo->samples)
9901                         {
9902                                 for (j = 0;j < surfacenumvertices;j++)
9903                                 {
9904                                         lm = surface->lightmapinfo->samples + offsets[j];
9905                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9906                                         VectorScale(lm, scale, c);
9907                                         if (surface->lightmapinfo->styles[1] != 255)
9908                                         {
9909                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9910                                                 lm += size3;
9911                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9912                                                 VectorMA(c, scale, lm, c);
9913                                                 if (surface->lightmapinfo->styles[2] != 255)
9914                                                 {
9915                                                         lm += size3;
9916                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9917                                                         VectorMA(c, scale, lm, c);
9918                                                         if (surface->lightmapinfo->styles[3] != 255)
9919                                                         {
9920                                                                 lm += size3;
9921                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9922                                                                 VectorMA(c, scale, lm, c);
9923                                                         }
9924                                                 }
9925                                         }
9926                                         c[0] >>= 7;
9927                                         c[1] >>= 7;
9928                                         c[2] >>= 7;
9929                                         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);
9930                                         numvertices++;
9931                                 }
9932                         }
9933                         else
9934                         {
9935                                 for (j = 0;j < surfacenumvertices;j++)
9936                                 {
9937                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9938                                         numvertices++;
9939                                 }
9940                         }
9941                 }
9942         }
9943
9944         // if vertices are deformed (sprite flares and things in maps, possibly
9945         // water waves, bulges and other deformations), modify the copied vertices
9946         // in place
9947         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9948         {
9949                 float scale;
9950                 switch (deform->deform)
9951                 {
9952                 default:
9953                 case Q3DEFORM_PROJECTIONSHADOW:
9954                 case Q3DEFORM_TEXT0:
9955                 case Q3DEFORM_TEXT1:
9956                 case Q3DEFORM_TEXT2:
9957                 case Q3DEFORM_TEXT3:
9958                 case Q3DEFORM_TEXT4:
9959                 case Q3DEFORM_TEXT5:
9960                 case Q3DEFORM_TEXT6:
9961                 case Q3DEFORM_TEXT7:
9962                 case Q3DEFORM_NONE:
9963                         break;
9964                 case Q3DEFORM_AUTOSPRITE:
9965                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9966                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9967                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9968                         VectorNormalize(newforward);
9969                         VectorNormalize(newright);
9970                         VectorNormalize(newup);
9971 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9972 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9973 //                      rsurface.batchvertex3f_bufferoffset = 0;
9974 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9975 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9976 //                      rsurface.batchsvector3f_bufferoffset = 0;
9977 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9978 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9979 //                      rsurface.batchtvector3f_bufferoffset = 0;
9980 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9981 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9982 //                      rsurface.batchnormal3f_bufferoffset = 0;
9983                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9984                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9985                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9986                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9987                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9988                         // a single autosprite surface can contain multiple sprites...
9989                         for (j = 0;j < batchnumvertices - 3;j += 4)
9990                         {
9991                                 VectorClear(center);
9992                                 for (i = 0;i < 4;i++)
9993                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9994                                 VectorScale(center, 0.25f, center);
9995                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9996                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9997                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9998                                 for (i = 0;i < 4;i++)
9999                                 {
10000                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10001                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
10002                                 }
10003                         }
10004                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
10005                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10006                         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);
10007                         break;
10008                 case Q3DEFORM_AUTOSPRITE2:
10009                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10010                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10011                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10012                         VectorNormalize(newforward);
10013                         VectorNormalize(newright);
10014                         VectorNormalize(newup);
10015 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10016 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10017 //                      rsurface.batchvertex3f_bufferoffset = 0;
10018                         {
10019                                 const float *v1, *v2;
10020                                 vec3_t start, end;
10021                                 float f, l;
10022                                 struct
10023                                 {
10024                                         float length2;
10025                                         const float *v1;
10026                                         const float *v2;
10027                                 }
10028                                 shortest[2];
10029                                 memset(shortest, 0, sizeof(shortest));
10030                                 // a single autosprite surface can contain multiple sprites...
10031                                 for (j = 0;j < batchnumvertices - 3;j += 4)
10032                                 {
10033                                         VectorClear(center);
10034                                         for (i = 0;i < 4;i++)
10035                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10036                                         VectorScale(center, 0.25f, center);
10037                                         // find the two shortest edges, then use them to define the
10038                                         // axis vectors for rotating around the central axis
10039                                         for (i = 0;i < 6;i++)
10040                                         {
10041                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10042                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10043                                                 l = VectorDistance2(v1, v2);
10044                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10045                                                 if (v1[2] != v2[2])
10046                                                         l += (1.0f / 1024.0f);
10047                                                 if (shortest[0].length2 > l || i == 0)
10048                                                 {
10049                                                         shortest[1] = shortest[0];
10050                                                         shortest[0].length2 = l;
10051                                                         shortest[0].v1 = v1;
10052                                                         shortest[0].v2 = v2;
10053                                                 }
10054                                                 else if (shortest[1].length2 > l || i == 1)
10055                                                 {
10056                                                         shortest[1].length2 = l;
10057                                                         shortest[1].v1 = v1;
10058                                                         shortest[1].v2 = v2;
10059                                                 }
10060                                         }
10061                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10062                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10063                                         // this calculates the right vector from the shortest edge
10064                                         // and the up vector from the edge midpoints
10065                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10066                                         VectorNormalize(right);
10067                                         VectorSubtract(end, start, up);
10068                                         VectorNormalize(up);
10069                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10070                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10071                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10072                                         VectorNegate(forward, forward);
10073                                         VectorReflect(forward, 0, up, forward);
10074                                         VectorNormalize(forward);
10075                                         CrossProduct(up, forward, newright);
10076                                         VectorNormalize(newright);
10077                                         // rotate the quad around the up axis vector, this is made
10078                                         // especially easy by the fact we know the quad is flat,
10079                                         // so we only have to subtract the center position and
10080                                         // measure distance along the right vector, and then
10081                                         // multiply that by the newright vector and add back the
10082                                         // center position
10083                                         // we also need to subtract the old position to undo the
10084                                         // displacement from the center, which we do with a
10085                                         // DotProduct, the subtraction/addition of center is also
10086                                         // optimized into DotProducts here
10087                                         l = DotProduct(right, center);
10088                                         for (i = 0;i < 4;i++)
10089                                         {
10090                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10091                                                 f = DotProduct(right, v1) - l;
10092                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10093                                         }
10094                                 }
10095                         }
10096                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10097                         {
10098 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10099 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10100 //                              rsurface.batchnormal3f_bufferoffset = 0;
10101                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10102                         }
10103                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10104                         {
10105 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10106 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10107 //                              rsurface.batchsvector3f_bufferoffset = 0;
10108 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10109 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10110 //                              rsurface.batchtvector3f_bufferoffset = 0;
10111                                 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);
10112                         }
10113                         break;
10114                 case Q3DEFORM_NORMAL:
10115                         // deform the normals to make reflections wavey
10116                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10117                         rsurface.batchnormal3f_vertexbuffer = NULL;
10118                         rsurface.batchnormal3f_bufferoffset = 0;
10119                         for (j = 0;j < batchnumvertices;j++)
10120                         {
10121                                 float vertex[3];
10122                                 float *normal = rsurface.batchnormal3f + 3*j;
10123                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10124                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10125                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10126                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10127                                 VectorNormalize(normal);
10128                         }
10129                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10130                         {
10131 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10132 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10133 //                              rsurface.batchsvector3f_bufferoffset = 0;
10134 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10135 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10136 //                              rsurface.batchtvector3f_bufferoffset = 0;
10137                                 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);
10138                         }
10139                         break;
10140                 case Q3DEFORM_WAVE:
10141                         // deform vertex array to make wavey water and flags and such
10142                         waveparms[0] = deform->waveparms[0];
10143                         waveparms[1] = deform->waveparms[1];
10144                         waveparms[2] = deform->waveparms[2];
10145                         waveparms[3] = deform->waveparms[3];
10146                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10147                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10148                         // this is how a divisor of vertex influence on deformation
10149                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10150                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10151 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10152 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10153 //                      rsurface.batchvertex3f_bufferoffset = 0;
10154 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10155 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10156 //                      rsurface.batchnormal3f_bufferoffset = 0;
10157                         for (j = 0;j < batchnumvertices;j++)
10158                         {
10159                                 // if the wavefunc depends on time, evaluate it per-vertex
10160                                 if (waveparms[3])
10161                                 {
10162                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10163                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10164                                 }
10165                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10166                         }
10167                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10168                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10169                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10170                         {
10171 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10172 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10173 //                              rsurface.batchsvector3f_bufferoffset = 0;
10174 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10175 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10176 //                              rsurface.batchtvector3f_bufferoffset = 0;
10177                                 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);
10178                         }
10179                         break;
10180                 case Q3DEFORM_BULGE:
10181                         // deform vertex array to make the surface have moving bulges
10182 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10183 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10184 //                      rsurface.batchvertex3f_bufferoffset = 0;
10185 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10186 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10187 //                      rsurface.batchnormal3f_bufferoffset = 0;
10188                         for (j = 0;j < batchnumvertices;j++)
10189                         {
10190                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10191                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10192                         }
10193                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10194                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10195                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10196                         {
10197 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10198 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10199 //                              rsurface.batchsvector3f_bufferoffset = 0;
10200 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10201 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10202 //                              rsurface.batchtvector3f_bufferoffset = 0;
10203                                 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);
10204                         }
10205                         break;
10206                 case Q3DEFORM_MOVE:
10207                         // deform vertex array
10208                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10209                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10210                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10211                         VectorScale(deform->parms, scale, waveparms);
10212 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10213 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10214 //                      rsurface.batchvertex3f_bufferoffset = 0;
10215                         for (j = 0;j < batchnumvertices;j++)
10216                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10217                         break;
10218                 }
10219         }
10220
10221         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10222         {
10223         // generate texcoords based on the chosen texcoord source
10224                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10225                 {
10226                 default:
10227                 case Q3TCGEN_TEXTURE:
10228                         break;
10229                 case Q3TCGEN_LIGHTMAP:
10230         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10231         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10232         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10233                         if (rsurface.batchtexcoordlightmap2f)
10234                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10235                         break;
10236                 case Q3TCGEN_VECTOR:
10237         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10238         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10239         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10240                         for (j = 0;j < batchnumvertices;j++)
10241                         {
10242                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10243                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10244                         }
10245                         break;
10246                 case Q3TCGEN_ENVIRONMENT:
10247                         // make environment reflections using a spheremap
10248                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10249                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10250                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10251                         for (j = 0;j < batchnumvertices;j++)
10252                         {
10253                                 // identical to Q3A's method, but executed in worldspace so
10254                                 // carried models can be shiny too
10255
10256                                 float viewer[3], d, reflected[3], worldreflected[3];
10257
10258                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10259                                 // VectorNormalize(viewer);
10260
10261                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10262
10263                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10264                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10265                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10266                                 // note: this is proportinal to viewer, so we can normalize later
10267
10268                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10269                                 VectorNormalize(worldreflected);
10270
10271                                 // note: this sphere map only uses world x and z!
10272                                 // so positive and negative y will LOOK THE SAME.
10273                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10274                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10275                         }
10276                         break;
10277                 }
10278                 // the only tcmod that needs software vertex processing is turbulent, so
10279                 // check for it here and apply the changes if needed
10280                 // and we only support that as the first one
10281                 // (handling a mixture of turbulent and other tcmods would be problematic
10282                 //  without punting it entirely to a software path)
10283                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10284                 {
10285                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10286                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10287         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10288         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10289         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10290                         for (j = 0;j < batchnumvertices;j++)
10291                         {
10292                                 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);
10293                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10294                         }
10295                 }
10296         }
10297
10298         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10299         {
10300                 // convert the modified arrays to vertex structs
10301 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10302 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10303 //              rsurface.batchvertexmesh_bufferoffset = 0;
10304                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10305                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10306                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10307                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10308                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10309                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10310                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10311                 {
10312                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10313                         {
10314                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10315                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10316                         }
10317                 }
10318                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10319                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10320                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10321                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10322                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10323                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10324                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10325                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10326                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10327                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10328                 {
10329                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10330                         {
10331                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10332                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10333                         }
10334                 }
10335         }
10336
10337         // upload buffer data for the dynamic batch
10338         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10339         {
10340                 if (rsurface.batchvertexmesh)
10341                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10342                 else
10343                 {
10344                         if (rsurface.batchvertex3f)
10345                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10346                         if (rsurface.batchsvector3f)
10347                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10348                         if (rsurface.batchtvector3f)
10349                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10350                         if (rsurface.batchnormal3f)
10351                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10352                         if (rsurface.batchlightmapcolor4f)
10353                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10354                         if (rsurface.batchtexcoordtexture2f)
10355                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10356                         if (rsurface.batchtexcoordlightmap2f)
10357                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10358                         if (rsurface.batchskeletalindex4ub)
10359                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10360                         if (rsurface.batchskeletalweight4ub)
10361                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10362                 }
10363                 if (rsurface.batchelement3s)
10364                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10365                 else if (rsurface.batchelement3i)
10366                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10367         }
10368 }
10369
10370 void RSurf_DrawBatch(void)
10371 {
10372         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10373         // through the pipeline, killing it earlier in the pipeline would have
10374         // per-surface overhead rather than per-batch overhead, so it's best to
10375         // reject it here, before it hits glDraw.
10376         if (rsurface.batchnumtriangles == 0)
10377                 return;
10378 #if 0
10379         // batch debugging code
10380         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10381         {
10382                 int i;
10383                 int j;
10384                 int c;
10385                 const int *e;
10386                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10387                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10388                 {
10389                         c = e[i];
10390                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10391                         {
10392                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10393                                 {
10394                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10395                                                 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);
10396                                         break;
10397                                 }
10398                         }
10399                 }
10400         }
10401 #endif
10402         if (rsurface.batchmultidraw)
10403         {
10404                 // issue multiple draws rather than copying index data
10405                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10406                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10407                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10408                 for (i = 0;i < numsurfaces;)
10409                 {
10410                         // combine consecutive surfaces as one draw
10411                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10412                                 if (surfacelist[j] != surfacelist[k] + 1)
10413                                         break;
10414                         firstvertex = surfacelist[i]->num_firstvertex;
10415                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10416                         firsttriangle = surfacelist[i]->num_firsttriangle;
10417                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10418                         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);
10419                         i = j;
10420                 }
10421         }
10422         else
10423         {
10424                 // there is only one consecutive run of index data (may have been combined)
10425                 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);
10426         }
10427 }
10428
10429 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10430 {
10431         // pick the closest matching water plane
10432         int planeindex, vertexindex, bestplaneindex = -1;
10433         float d, bestd;
10434         vec3_t vert;
10435         const float *v;
10436         r_waterstate_waterplane_t *p;
10437         qboolean prepared = false;
10438         bestd = 0;
10439         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10440         {
10441                 if(p->camera_entity != rsurface.texture->camera_entity)
10442                         continue;
10443                 d = 0;
10444                 if(!prepared)
10445                 {
10446                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10447                         prepared = true;
10448                         if(rsurface.batchnumvertices == 0)
10449                                 break;
10450                 }
10451                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10452                 {
10453                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10454                         d += fabs(PlaneDiff(vert, &p->plane));
10455                 }
10456                 if (bestd > d || bestplaneindex < 0)
10457                 {
10458                         bestd = d;
10459                         bestplaneindex = planeindex;
10460                 }
10461         }
10462         return bestplaneindex;
10463         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10464         // this situation though, as it might be better to render single larger
10465         // batches with useless stuff (backface culled for example) than to
10466         // render multiple smaller batches
10467 }
10468
10469 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10470 {
10471         int i;
10472         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10473         rsurface.passcolor4f_vertexbuffer = 0;
10474         rsurface.passcolor4f_bufferoffset = 0;
10475         for (i = 0;i < rsurface.batchnumvertices;i++)
10476                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10477 }
10478
10479 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10480 {
10481         int i;
10482         float f;
10483         const float *v;
10484         const float *c;
10485         float *c2;
10486         if (rsurface.passcolor4f)
10487         {
10488                 // generate color arrays
10489                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10490                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10491                 rsurface.passcolor4f_vertexbuffer = 0;
10492                 rsurface.passcolor4f_bufferoffset = 0;
10493                 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)
10494                 {
10495                         f = RSurf_FogVertex(v);
10496                         c2[0] = c[0] * f;
10497                         c2[1] = c[1] * f;
10498                         c2[2] = c[2] * f;
10499                         c2[3] = c[3];
10500                 }
10501         }
10502         else
10503         {
10504                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10505                 rsurface.passcolor4f_vertexbuffer = 0;
10506                 rsurface.passcolor4f_bufferoffset = 0;
10507                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10508                 {
10509                         f = RSurf_FogVertex(v);
10510                         c2[0] = f;
10511                         c2[1] = f;
10512                         c2[2] = f;
10513                         c2[3] = 1;
10514                 }
10515         }
10516 }
10517
10518 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10519 {
10520         int i;
10521         float f;
10522         const float *v;
10523         const float *c;
10524         float *c2;
10525         if (!rsurface.passcolor4f)
10526                 return;
10527         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10528         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10529         rsurface.passcolor4f_vertexbuffer = 0;
10530         rsurface.passcolor4f_bufferoffset = 0;
10531         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)
10532         {
10533                 f = RSurf_FogVertex(v);
10534                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10535                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10536                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10537                 c2[3] = c[3];
10538         }
10539 }
10540
10541 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10542 {
10543         int i;
10544         const float *c;
10545         float *c2;
10546         if (!rsurface.passcolor4f)
10547                 return;
10548         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10549         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10550         rsurface.passcolor4f_vertexbuffer = 0;
10551         rsurface.passcolor4f_bufferoffset = 0;
10552         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10553         {
10554                 c2[0] = c[0] * r;
10555                 c2[1] = c[1] * g;
10556                 c2[2] = c[2] * b;
10557                 c2[3] = c[3] * a;
10558         }
10559 }
10560
10561 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10562 {
10563         int i;
10564         const float *c;
10565         float *c2;
10566         if (!rsurface.passcolor4f)
10567                 return;
10568         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10569         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10570         rsurface.passcolor4f_vertexbuffer = 0;
10571         rsurface.passcolor4f_bufferoffset = 0;
10572         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10573         {
10574                 c2[0] = c[0] + r_refdef.scene.ambient;
10575                 c2[1] = c[1] + r_refdef.scene.ambient;
10576                 c2[2] = c[2] + r_refdef.scene.ambient;
10577                 c2[3] = c[3];
10578         }
10579 }
10580
10581 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10582 {
10583         // TODO: optimize
10584         rsurface.passcolor4f = NULL;
10585         rsurface.passcolor4f_vertexbuffer = 0;
10586         rsurface.passcolor4f_bufferoffset = 0;
10587         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10588         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10589         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10590         GL_Color(r, g, b, a);
10591         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10592         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10593         R_Mesh_TexMatrix(0, NULL);
10594         RSurf_DrawBatch();
10595 }
10596
10597 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10598 {
10599         // TODO: optimize applyfog && applycolor case
10600         // just apply fog if necessary, and tint the fog color array if necessary
10601         rsurface.passcolor4f = NULL;
10602         rsurface.passcolor4f_vertexbuffer = 0;
10603         rsurface.passcolor4f_bufferoffset = 0;
10604         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10605         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10606         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10607         GL_Color(r, g, b, a);
10608         RSurf_DrawBatch();
10609 }
10610
10611 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10612 {
10613         // TODO: optimize
10614         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10615         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10616         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10617         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10618         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10619         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10620         GL_Color(r, g, b, a);
10621         RSurf_DrawBatch();
10622 }
10623
10624 static void RSurf_DrawBatch_GL11_ClampColor(void)
10625 {
10626         int i;
10627         const float *c1;
10628         float *c2;
10629         if (!rsurface.passcolor4f)
10630                 return;
10631         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10632         {
10633                 c2[0] = bound(0.0f, c1[0], 1.0f);
10634                 c2[1] = bound(0.0f, c1[1], 1.0f);
10635                 c2[2] = bound(0.0f, c1[2], 1.0f);
10636                 c2[3] = bound(0.0f, c1[3], 1.0f);
10637         }
10638 }
10639
10640 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10641 {
10642         int i;
10643         float f;
10644         const float *v;
10645         const float *n;
10646         float *c;
10647         //vec3_t eyedir;
10648
10649         // fake shading
10650         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10651         rsurface.passcolor4f_vertexbuffer = 0;
10652         rsurface.passcolor4f_bufferoffset = 0;
10653         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)
10654         {
10655                 f = -DotProduct(r_refdef.view.forward, n);
10656                 f = max(0, f);
10657                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10658                 f *= r_refdef.lightmapintensity;
10659                 Vector4Set(c, f, f, f, 1);
10660         }
10661 }
10662
10663 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10664 {
10665         RSurf_DrawBatch_GL11_ApplyFakeLight();
10666         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10667         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10668         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10669         GL_Color(r, g, b, a);
10670         RSurf_DrawBatch();
10671 }
10672
10673 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10674 {
10675         int i;
10676         float f;
10677         float alpha;
10678         const float *v;
10679         const float *n;
10680         float *c;
10681         vec3_t ambientcolor;
10682         vec3_t diffusecolor;
10683         vec3_t lightdir;
10684         // TODO: optimize
10685         // model lighting
10686         VectorCopy(rsurface.modellight_lightdir, lightdir);
10687         f = 0.5f * r_refdef.lightmapintensity;
10688         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10689         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10690         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10691         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10692         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10693         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10694         alpha = *a;
10695         if (VectorLength2(diffusecolor) > 0)
10696         {
10697                 // q3-style directional shading
10698                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10699                 rsurface.passcolor4f_vertexbuffer = 0;
10700                 rsurface.passcolor4f_bufferoffset = 0;
10701                 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)
10702                 {
10703                         if ((f = DotProduct(n, lightdir)) > 0)
10704                                 VectorMA(ambientcolor, f, diffusecolor, c);
10705                         else
10706                                 VectorCopy(ambientcolor, c);
10707                         c[3] = alpha;
10708                 }
10709                 *r = 1;
10710                 *g = 1;
10711                 *b = 1;
10712                 *a = 1;
10713                 *applycolor = false;
10714         }
10715         else
10716         {
10717                 *r = ambientcolor[0];
10718                 *g = ambientcolor[1];
10719                 *b = ambientcolor[2];
10720                 rsurface.passcolor4f = NULL;
10721                 rsurface.passcolor4f_vertexbuffer = 0;
10722                 rsurface.passcolor4f_bufferoffset = 0;
10723         }
10724 }
10725
10726 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10727 {
10728         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10729         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10730         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10731         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10732         GL_Color(r, g, b, a);
10733         RSurf_DrawBatch();
10734 }
10735
10736 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10737 {
10738         int i;
10739         float f;
10740         const float *v;
10741         float *c;
10742
10743         // fake shading
10744         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10745         rsurface.passcolor4f_vertexbuffer = 0;
10746         rsurface.passcolor4f_bufferoffset = 0;
10747
10748         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10749         {
10750                 f = 1 - RSurf_FogVertex(v);
10751                 c[0] = r;
10752                 c[1] = g;
10753                 c[2] = b;
10754                 c[3] = f * a;
10755         }
10756 }
10757
10758 void RSurf_SetupDepthAndCulling(void)
10759 {
10760         // submodels are biased to avoid z-fighting with world surfaces that they
10761         // may be exactly overlapping (avoids z-fighting artifacts on certain
10762         // doors and things in Quake maps)
10763         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10764         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10765         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10766         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10767 }
10768
10769 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10770 {
10771         // transparent sky would be ridiculous
10772         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10773                 return;
10774         R_SetupShader_Generic_NoTexture(false, false);
10775         skyrenderlater = true;
10776         RSurf_SetupDepthAndCulling();
10777         GL_DepthMask(true);
10778         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10779         // skymasking on them, and Quake3 never did sky masking (unlike
10780         // software Quake and software Quake2), so disable the sky masking
10781         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10782         // and skymasking also looks very bad when noclipping outside the
10783         // level, so don't use it then either.
10784         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10785         {
10786                 R_Mesh_ResetTextureState();
10787                 if (skyrendermasked)
10788                 {
10789                         R_SetupShader_DepthOrShadow(false, false, false);
10790                         // depth-only (masking)
10791                         GL_ColorMask(0,0,0,0);
10792                         // just to make sure that braindead drivers don't draw
10793                         // anything despite that colormask...
10794                         GL_BlendFunc(GL_ZERO, GL_ONE);
10795                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10796                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10797                 }
10798                 else
10799                 {
10800                         R_SetupShader_Generic_NoTexture(false, false);
10801                         // fog sky
10802                         GL_BlendFunc(GL_ONE, GL_ZERO);
10803                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10804                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10805                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10806                 }
10807                 RSurf_DrawBatch();
10808                 if (skyrendermasked)
10809                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10810         }
10811         R_Mesh_ResetTextureState();
10812         GL_Color(1, 1, 1, 1);
10813 }
10814
10815 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10816 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10817 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10818 {
10819         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10820                 return;
10821         if (prepass)
10822         {
10823                 // render screenspace normalmap to texture
10824                 GL_DepthMask(true);
10825                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10826                 RSurf_DrawBatch();
10827                 return;
10828         }
10829
10830         // bind lightmap texture
10831
10832         // water/refraction/reflection/camera surfaces have to be handled specially
10833         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10834         {
10835                 int start, end, startplaneindex;
10836                 for (start = 0;start < texturenumsurfaces;start = end)
10837                 {
10838                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10839                         if(startplaneindex < 0)
10840                         {
10841                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10842                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10843                                 end = start + 1;
10844                                 continue;
10845                         }
10846                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10847                                 ;
10848                         // now that we have a batch using the same planeindex, render it
10849                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10850                         {
10851                                 // render water or distortion background
10852                                 GL_DepthMask(true);
10853                                 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);
10854                                 RSurf_DrawBatch();
10855                                 // blend surface on top
10856                                 GL_DepthMask(false);
10857                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10858                                 RSurf_DrawBatch();
10859                         }
10860                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10861                         {
10862                                 // render surface with reflection texture as input
10863                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10864                                 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);
10865                                 RSurf_DrawBatch();
10866                         }
10867                 }
10868                 return;
10869         }
10870
10871         // render surface batch normally
10872         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10873         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);
10874         RSurf_DrawBatch();
10875 }
10876
10877 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10878 {
10879         // OpenGL 1.3 path - anything not completely ancient
10880         qboolean applycolor;
10881         qboolean applyfog;
10882         int layerindex;
10883         const texturelayer_t *layer;
10884         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);
10885         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10886
10887         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10888         {
10889                 vec4_t layercolor;
10890                 int layertexrgbscale;
10891                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10892                 {
10893                         if (layerindex == 0)
10894                                 GL_AlphaTest(true);
10895                         else
10896                         {
10897                                 GL_AlphaTest(false);
10898                                 GL_DepthFunc(GL_EQUAL);
10899                         }
10900                 }
10901                 GL_DepthMask(layer->depthmask && writedepth);
10902                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10903                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10904                 {
10905                         layertexrgbscale = 4;
10906                         VectorScale(layer->color, 0.25f, layercolor);
10907                 }
10908                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10909                 {
10910                         layertexrgbscale = 2;
10911                         VectorScale(layer->color, 0.5f, layercolor);
10912                 }
10913                 else
10914                 {
10915                         layertexrgbscale = 1;
10916                         VectorScale(layer->color, 1.0f, layercolor);
10917                 }
10918                 layercolor[3] = layer->color[3];
10919                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10920                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10921                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10922                 switch (layer->type)
10923                 {
10924                 case TEXTURELAYERTYPE_LITTEXTURE:
10925                         // single-pass lightmapped texture with 2x rgbscale
10926                         R_Mesh_TexBind(0, r_texture_white);
10927                         R_Mesh_TexMatrix(0, NULL);
10928                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10929                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10930                         R_Mesh_TexBind(1, layer->texture);
10931                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10932                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10933                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10934                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10935                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10936                         else if (FAKELIGHT_ENABLED)
10937                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10938                         else if (rsurface.uselightmaptexture)
10939                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10940                         else
10941                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10942                         break;
10943                 case TEXTURELAYERTYPE_TEXTURE:
10944                         // singletexture unlit texture with transparency support
10945                         R_Mesh_TexBind(0, layer->texture);
10946                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10947                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10948                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10949                         R_Mesh_TexBind(1, 0);
10950                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10951                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10952                         break;
10953                 case TEXTURELAYERTYPE_FOG:
10954                         // singletexture fogging
10955                         if (layer->texture)
10956                         {
10957                                 R_Mesh_TexBind(0, layer->texture);
10958                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10959                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10960                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10961                         }
10962                         else
10963                         {
10964                                 R_Mesh_TexBind(0, 0);
10965                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10966                         }
10967                         R_Mesh_TexBind(1, 0);
10968                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10969                         // generate a color array for the fog pass
10970                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10971                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10972                         RSurf_DrawBatch();
10973                         break;
10974                 default:
10975                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10976                 }
10977         }
10978         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10979         {
10980                 GL_DepthFunc(GL_LEQUAL);
10981                 GL_AlphaTest(false);
10982         }
10983 }
10984
10985 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10986 {
10987         // OpenGL 1.1 - crusty old voodoo path
10988         qboolean applyfog;
10989         int layerindex;
10990         const texturelayer_t *layer;
10991         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);
10992         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10993
10994         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10995         {
10996                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10997                 {
10998                         if (layerindex == 0)
10999                                 GL_AlphaTest(true);
11000                         else
11001                         {
11002                                 GL_AlphaTest(false);
11003                                 GL_DepthFunc(GL_EQUAL);
11004                         }
11005                 }
11006                 GL_DepthMask(layer->depthmask && writedepth);
11007                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11008                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11009                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11010                 switch (layer->type)
11011                 {
11012                 case TEXTURELAYERTYPE_LITTEXTURE:
11013                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
11014                         {
11015                                 // two-pass lit texture with 2x rgbscale
11016                                 // first the lightmap pass
11017                                 R_Mesh_TexBind(0, r_texture_white);
11018                                 R_Mesh_TexMatrix(0, NULL);
11019                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11020                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11021                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11022                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11023                                 else if (FAKELIGHT_ENABLED)
11024                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
11025                                 else if (rsurface.uselightmaptexture)
11026                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11027                                 else
11028                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11029                                 // then apply the texture to it
11030                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11031                                 R_Mesh_TexBind(0, layer->texture);
11032                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11033                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11034                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11035                                 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);
11036                         }
11037                         else
11038                         {
11039                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11040                                 R_Mesh_TexBind(0, layer->texture);
11041                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11042                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11043                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11044                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11045                                         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);
11046                                 else if (FAKELIGHT_ENABLED)
11047                                         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);
11048                                 else
11049                                         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);
11050                         }
11051                         break;
11052                 case TEXTURELAYERTYPE_TEXTURE:
11053                         // singletexture unlit texture with transparency support
11054                         R_Mesh_TexBind(0, layer->texture);
11055                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11056                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11057                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11058                         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);
11059                         break;
11060                 case TEXTURELAYERTYPE_FOG:
11061                         // singletexture fogging
11062                         if (layer->texture)
11063                         {
11064                                 R_Mesh_TexBind(0, layer->texture);
11065                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11066                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11067                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11068                         }
11069                         else
11070                         {
11071                                 R_Mesh_TexBind(0, 0);
11072                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11073                         }
11074                         // generate a color array for the fog pass
11075                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11076                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11077                         RSurf_DrawBatch();
11078                         break;
11079                 default:
11080                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11081                 }
11082         }
11083         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11084         {
11085                 GL_DepthFunc(GL_LEQUAL);
11086                 GL_AlphaTest(false);
11087         }
11088 }
11089
11090 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11091 {
11092         int vi;
11093         int j;
11094         r_vertexgeneric_t *batchvertex;
11095         float c[4];
11096
11097 //      R_Mesh_ResetTextureState();
11098         R_SetupShader_Generic_NoTexture(false, false);
11099
11100         if(rsurface.texture && rsurface.texture->currentskinframe)
11101         {
11102                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11103                 c[3] *= rsurface.texture->currentalpha;
11104         }
11105         else
11106         {
11107                 c[0] = 1;
11108                 c[1] = 0;
11109                 c[2] = 1;
11110                 c[3] = 1;
11111         }
11112
11113         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11114         {
11115                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11116                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11117                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11118         }
11119
11120         // brighten it up (as texture value 127 means "unlit")
11121         c[0] *= 2 * r_refdef.view.colorscale;
11122         c[1] *= 2 * r_refdef.view.colorscale;
11123         c[2] *= 2 * r_refdef.view.colorscale;
11124
11125         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11126                 c[3] *= r_wateralpha.value;
11127
11128         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11129         {
11130                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11131                 GL_DepthMask(false);
11132         }
11133         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11134         {
11135                 GL_BlendFunc(GL_ONE, GL_ONE);
11136                 GL_DepthMask(false);
11137         }
11138         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11139         {
11140                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11141                 GL_DepthMask(false);
11142         }
11143         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11144         {
11145                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11146                 GL_DepthMask(false);
11147         }
11148         else
11149         {
11150                 GL_BlendFunc(GL_ONE, GL_ZERO);
11151                 GL_DepthMask(writedepth);
11152         }
11153
11154         if (r_showsurfaces.integer == 3)
11155         {
11156                 rsurface.passcolor4f = NULL;
11157
11158                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11159                 {
11160                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11161
11162                         rsurface.passcolor4f = NULL;
11163                         rsurface.passcolor4f_vertexbuffer = 0;
11164                         rsurface.passcolor4f_bufferoffset = 0;
11165                 }
11166                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11167                 {
11168                         qboolean applycolor = true;
11169                         float one = 1.0;
11170
11171                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11172
11173                         r_refdef.lightmapintensity = 1;
11174                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11175                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11176                 }
11177                 else if (FAKELIGHT_ENABLED)
11178                 {
11179                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11180
11181                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11182                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11183                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11184                 }
11185                 else
11186                 {
11187                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11188
11189                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11190                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11191                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11192                 }
11193
11194                 if(!rsurface.passcolor4f)
11195                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11196
11197                 RSurf_DrawBatch_GL11_ApplyAmbient();
11198                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11199                 if(r_refdef.fogenabled)
11200                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11201                 RSurf_DrawBatch_GL11_ClampColor();
11202
11203                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11204                 R_SetupShader_Generic_NoTexture(false, false);
11205                 RSurf_DrawBatch();
11206         }
11207         else if (!r_refdef.view.showdebug)
11208         {
11209                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11210                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11211                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11212                 {
11213                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11214                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11215                 }
11216                 R_Mesh_PrepareVertices_Generic_Unlock();
11217                 RSurf_DrawBatch();
11218         }
11219         else if (r_showsurfaces.integer == 4)
11220         {
11221                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11222                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11223                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11224                 {
11225                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11226                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11227                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11228                 }
11229                 R_Mesh_PrepareVertices_Generic_Unlock();
11230                 RSurf_DrawBatch();
11231         }
11232         else if (r_showsurfaces.integer == 2)
11233         {
11234                 const int *e;
11235                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11236                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11237                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11238                 {
11239                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11240                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11241                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11242                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11243                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11244                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11245                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11246                 }
11247                 R_Mesh_PrepareVertices_Generic_Unlock();
11248                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11249         }
11250         else
11251         {
11252                 int texturesurfaceindex;
11253                 int k;
11254                 const msurface_t *surface;
11255                 float surfacecolor4f[4];
11256                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11257                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11258                 vi = 0;
11259                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11260                 {
11261                         surface = texturesurfacelist[texturesurfaceindex];
11262                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11263                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11264                         for (j = 0;j < surface->num_vertices;j++)
11265                         {
11266                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11267                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11268                                 vi++;
11269                         }
11270                 }
11271                 R_Mesh_PrepareVertices_Generic_Unlock();
11272                 RSurf_DrawBatch();
11273         }
11274 }
11275
11276 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11277 {
11278         CHECKGLERROR
11279         RSurf_SetupDepthAndCulling();
11280         if (r_showsurfaces.integer)
11281         {
11282                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11283                 return;
11284         }
11285         switch (vid.renderpath)
11286         {
11287         case RENDERPATH_GL20:
11288         case RENDERPATH_D3D9:
11289         case RENDERPATH_D3D10:
11290         case RENDERPATH_D3D11:
11291         case RENDERPATH_SOFT:
11292         case RENDERPATH_GLES2:
11293                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11294                 break;
11295         case RENDERPATH_GL13:
11296         case RENDERPATH_GLES1:
11297                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11298                 break;
11299         case RENDERPATH_GL11:
11300                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11301                 break;
11302         }
11303         CHECKGLERROR
11304 }
11305
11306 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11307 {
11308         CHECKGLERROR
11309         RSurf_SetupDepthAndCulling();
11310         if (r_showsurfaces.integer)
11311         {
11312                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11313                 return;
11314         }
11315         switch (vid.renderpath)
11316         {
11317         case RENDERPATH_GL20:
11318         case RENDERPATH_D3D9:
11319         case RENDERPATH_D3D10:
11320         case RENDERPATH_D3D11:
11321         case RENDERPATH_SOFT:
11322         case RENDERPATH_GLES2:
11323                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11324                 break;
11325         case RENDERPATH_GL13:
11326         case RENDERPATH_GLES1:
11327                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11328                 break;
11329         case RENDERPATH_GL11:
11330                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11331                 break;
11332         }
11333         CHECKGLERROR
11334 }
11335
11336 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11337 {
11338         int i, j;
11339         int texturenumsurfaces, endsurface;
11340         texture_t *texture;
11341         const msurface_t *surface;
11342         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11343
11344         // if the model is static it doesn't matter what value we give for
11345         // wantnormals and wanttangents, so this logic uses only rules applicable
11346         // to a model, knowing that they are meaningless otherwise
11347         if (ent == r_refdef.scene.worldentity)
11348                 RSurf_ActiveWorldEntity();
11349         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11350                 RSurf_ActiveModelEntity(ent, false, false, false);
11351         else
11352         {
11353                 switch (vid.renderpath)
11354                 {
11355                 case RENDERPATH_GL20:
11356                 case RENDERPATH_D3D9:
11357                 case RENDERPATH_D3D10:
11358                 case RENDERPATH_D3D11:
11359                 case RENDERPATH_SOFT:
11360                 case RENDERPATH_GLES2:
11361                         RSurf_ActiveModelEntity(ent, true, true, false);
11362                         break;
11363                 case RENDERPATH_GL11:
11364                 case RENDERPATH_GL13:
11365                 case RENDERPATH_GLES1:
11366                         RSurf_ActiveModelEntity(ent, true, false, false);
11367                         break;
11368                 }
11369         }
11370
11371         if (r_transparentdepthmasking.integer)
11372         {
11373                 qboolean setup = false;
11374                 for (i = 0;i < numsurfaces;i = j)
11375                 {
11376                         j = i + 1;
11377                         surface = rsurface.modelsurfaces + surfacelist[i];
11378                         texture = surface->texture;
11379                         rsurface.texture = R_GetCurrentTexture(texture);
11380                         rsurface.lightmaptexture = NULL;
11381                         rsurface.deluxemaptexture = NULL;
11382                         rsurface.uselightmaptexture = false;
11383                         // scan ahead until we find a different texture
11384                         endsurface = min(i + 1024, numsurfaces);
11385                         texturenumsurfaces = 0;
11386                         texturesurfacelist[texturenumsurfaces++] = surface;
11387                         for (;j < endsurface;j++)
11388                         {
11389                                 surface = rsurface.modelsurfaces + surfacelist[j];
11390                                 if (texture != surface->texture)
11391                                         break;
11392                                 texturesurfacelist[texturenumsurfaces++] = surface;
11393                         }
11394                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11395                                 continue;
11396                         // render the range of surfaces as depth
11397                         if (!setup)
11398                         {
11399                                 setup = true;
11400                                 GL_ColorMask(0,0,0,0);
11401                                 GL_Color(1,1,1,1);
11402                                 GL_DepthTest(true);
11403                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11404                                 GL_DepthMask(true);
11405 //                              R_Mesh_ResetTextureState();
11406                         }
11407                         RSurf_SetupDepthAndCulling();
11408                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11409                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11410                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11411                         RSurf_DrawBatch();
11412                 }
11413                 if (setup)
11414                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11415         }
11416
11417         for (i = 0;i < numsurfaces;i = j)
11418         {
11419                 j = i + 1;
11420                 surface = rsurface.modelsurfaces + surfacelist[i];
11421                 texture = surface->texture;
11422                 rsurface.texture = R_GetCurrentTexture(texture);
11423                 // scan ahead until we find a different texture
11424                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11425                 texturenumsurfaces = 0;
11426                 texturesurfacelist[texturenumsurfaces++] = surface;
11427                 if(FAKELIGHT_ENABLED)
11428                 {
11429                         rsurface.lightmaptexture = NULL;
11430                         rsurface.deluxemaptexture = NULL;
11431                         rsurface.uselightmaptexture = false;
11432                         for (;j < endsurface;j++)
11433                         {
11434                                 surface = rsurface.modelsurfaces + surfacelist[j];
11435                                 if (texture != surface->texture)
11436                                         break;
11437                                 texturesurfacelist[texturenumsurfaces++] = surface;
11438                         }
11439                 }
11440                 else
11441                 {
11442                         rsurface.lightmaptexture = surface->lightmaptexture;
11443                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11444                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11445                         for (;j < endsurface;j++)
11446                         {
11447                                 surface = rsurface.modelsurfaces + surfacelist[j];
11448                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11449                                         break;
11450                                 texturesurfacelist[texturenumsurfaces++] = surface;
11451                         }
11452                 }
11453                 // render the range of surfaces
11454                 if (ent == r_refdef.scene.worldentity)
11455                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11456                 else
11457                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11458         }
11459         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11460 }
11461
11462 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11463 {
11464         // transparent surfaces get pushed off into the transparent queue
11465         int surfacelistindex;
11466         const msurface_t *surface;
11467         vec3_t tempcenter, center;
11468         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11469         {
11470                 surface = texturesurfacelist[surfacelistindex];
11471                 if (r_transparent_sortsurfacesbynearest.integer)
11472                 {
11473                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11474                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11475                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11476                 }
11477                 else
11478                 {
11479                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11480                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11481                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11482                 }
11483                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11484                 if (rsurface.entity->transparent_offset) // transparent offset
11485                 {
11486                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11487                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11488                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11489                 }
11490                 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);
11491         }
11492 }
11493
11494 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11495 {
11496         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11497                 return;
11498         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11499                 return;
11500         RSurf_SetupDepthAndCulling();
11501         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11502         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11503         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11504         RSurf_DrawBatch();
11505 }
11506
11507 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11508 {
11509         CHECKGLERROR
11510         if (depthonly)
11511                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11512         else if (prepass)
11513         {
11514                 if (!rsurface.texture->currentnumlayers)
11515                         return;
11516                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11517                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11518                 else
11519                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11520         }
11521         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11522                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11523         else if (!rsurface.texture->currentnumlayers)
11524                 return;
11525         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11526         {
11527                 // in the deferred case, transparent surfaces were queued during prepass
11528                 if (!r_shadow_usingdeferredprepass)
11529                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11530         }
11531         else
11532         {
11533                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11534                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11535         }
11536         CHECKGLERROR
11537 }
11538
11539 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11540 {
11541         int i, j;
11542         texture_t *texture;
11543         R_FrameData_SetMark();
11544         // break the surface list down into batches by texture and use of lightmapping
11545         for (i = 0;i < numsurfaces;i = j)
11546         {
11547                 j = i + 1;
11548                 // texture is the base texture pointer, rsurface.texture is the
11549                 // current frame/skin the texture is directing us to use (for example
11550                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11551                 // use skin 1 instead)
11552                 texture = surfacelist[i]->texture;
11553                 rsurface.texture = R_GetCurrentTexture(texture);
11554                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11555                 {
11556                         // if this texture is not the kind we want, skip ahead to the next one
11557                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11558                                 ;
11559                         continue;
11560                 }
11561                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11562                 {
11563                         rsurface.lightmaptexture = NULL;
11564                         rsurface.deluxemaptexture = NULL;
11565                         rsurface.uselightmaptexture = false;
11566                         // simply scan ahead until we find a different texture or lightmap state
11567                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11568                                 ;
11569                 }
11570                 else
11571                 {
11572                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11573                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11574                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11575                         // simply scan ahead until we find a different texture or lightmap state
11576                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11577                                 ;
11578                 }
11579                 // render the range of surfaces
11580                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11581         }
11582         R_FrameData_ReturnToMark();
11583 }
11584
11585 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11586 {
11587         CHECKGLERROR
11588         if (depthonly)
11589                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11590         else if (prepass)
11591         {
11592                 if (!rsurface.texture->currentnumlayers)
11593                         return;
11594                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11595                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11596                 else
11597                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11598         }
11599         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11600                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11601         else if (!rsurface.texture->currentnumlayers)
11602                 return;
11603         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11604         {
11605                 // in the deferred case, transparent surfaces were queued during prepass
11606                 if (!r_shadow_usingdeferredprepass)
11607                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11608         }
11609         else
11610         {
11611                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11612                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11613         }
11614         CHECKGLERROR
11615 }
11616
11617 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11618 {
11619         int i, j;
11620         texture_t *texture;
11621         R_FrameData_SetMark();
11622         // break the surface list down into batches by texture and use of lightmapping
11623         for (i = 0;i < numsurfaces;i = j)
11624         {
11625                 j = i + 1;
11626                 // texture is the base texture pointer, rsurface.texture is the
11627                 // current frame/skin the texture is directing us to use (for example
11628                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11629                 // use skin 1 instead)
11630                 texture = surfacelist[i]->texture;
11631                 rsurface.texture = R_GetCurrentTexture(texture);
11632                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11633                 {
11634                         // if this texture is not the kind we want, skip ahead to the next one
11635                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11636                                 ;
11637                         continue;
11638                 }
11639                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11640                 {
11641                         rsurface.lightmaptexture = NULL;
11642                         rsurface.deluxemaptexture = NULL;
11643                         rsurface.uselightmaptexture = false;
11644                         // simply scan ahead until we find a different texture or lightmap state
11645                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11646                                 ;
11647                 }
11648                 else
11649                 {
11650                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11651                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11652                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11653                         // simply scan ahead until we find a different texture or lightmap state
11654                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11655                                 ;
11656                 }
11657                 // render the range of surfaces
11658                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11659         }
11660         R_FrameData_ReturnToMark();
11661 }
11662
11663 float locboxvertex3f[6*4*3] =
11664 {
11665         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11666         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11667         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11668         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11669         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11670         1,0,0, 0,0,0, 0,1,0, 1,1,0
11671 };
11672
11673 unsigned short locboxelements[6*2*3] =
11674 {
11675          0, 1, 2, 0, 2, 3,
11676          4, 5, 6, 4, 6, 7,
11677          8, 9,10, 8,10,11,
11678         12,13,14, 12,14,15,
11679         16,17,18, 16,18,19,
11680         20,21,22, 20,22,23
11681 };
11682
11683 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11684 {
11685         int i, j;
11686         cl_locnode_t *loc = (cl_locnode_t *)ent;
11687         vec3_t mins, size;
11688         float vertex3f[6*4*3];
11689         CHECKGLERROR
11690         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11691         GL_DepthMask(false);
11692         GL_DepthRange(0, 1);
11693         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11694         GL_DepthTest(true);
11695         GL_CullFace(GL_NONE);
11696         R_EntityMatrix(&identitymatrix);
11697
11698 //      R_Mesh_ResetTextureState();
11699
11700         i = surfacelist[0];
11701         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11702                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11703                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11704                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11705
11706         if (VectorCompare(loc->mins, loc->maxs))
11707         {
11708                 VectorSet(size, 2, 2, 2);
11709                 VectorMA(loc->mins, -0.5f, size, mins);
11710         }
11711         else
11712         {
11713                 VectorCopy(loc->mins, mins);
11714                 VectorSubtract(loc->maxs, loc->mins, size);
11715         }
11716
11717         for (i = 0;i < 6*4*3;)
11718                 for (j = 0;j < 3;j++, i++)
11719                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11720
11721         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11722         R_SetupShader_Generic_NoTexture(false, false);
11723         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11724 }
11725
11726 void R_DrawLocs(void)
11727 {
11728         int index;
11729         cl_locnode_t *loc, *nearestloc;
11730         vec3_t center;
11731         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11732         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11733         {
11734                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11735                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11736         }
11737 }
11738
11739 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11740 {
11741         if (decalsystem->decals)
11742                 Mem_Free(decalsystem->decals);
11743         memset(decalsystem, 0, sizeof(*decalsystem));
11744 }
11745
11746 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)
11747 {
11748         tridecal_t *decal;
11749         tridecal_t *decals;
11750         int i;
11751
11752         // expand or initialize the system
11753         if (decalsystem->maxdecals <= decalsystem->numdecals)
11754         {
11755                 decalsystem_t old = *decalsystem;
11756                 qboolean useshortelements;
11757                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11758                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11759                 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)));
11760                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11761                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11762                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11763                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11764                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11765                 if (decalsystem->numdecals)
11766                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11767                 if (old.decals)
11768                         Mem_Free(old.decals);
11769                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11770                         decalsystem->element3i[i] = i;
11771                 if (useshortelements)
11772                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11773                                 decalsystem->element3s[i] = i;
11774         }
11775
11776         // grab a decal and search for another free slot for the next one
11777         decals = decalsystem->decals;
11778         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11779         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11780                 ;
11781         decalsystem->freedecal = i;
11782         if (decalsystem->numdecals <= i)
11783                 decalsystem->numdecals = i + 1;
11784
11785         // initialize the decal
11786         decal->lived = 0;
11787         decal->triangleindex = triangleindex;
11788         decal->surfaceindex = surfaceindex;
11789         decal->decalsequence = decalsequence;
11790         decal->color4f[0][0] = c0[0];
11791         decal->color4f[0][1] = c0[1];
11792         decal->color4f[0][2] = c0[2];
11793         decal->color4f[0][3] = 1;
11794         decal->color4f[1][0] = c1[0];
11795         decal->color4f[1][1] = c1[1];
11796         decal->color4f[1][2] = c1[2];
11797         decal->color4f[1][3] = 1;
11798         decal->color4f[2][0] = c2[0];
11799         decal->color4f[2][1] = c2[1];
11800         decal->color4f[2][2] = c2[2];
11801         decal->color4f[2][3] = 1;
11802         decal->vertex3f[0][0] = v0[0];
11803         decal->vertex3f[0][1] = v0[1];
11804         decal->vertex3f[0][2] = v0[2];
11805         decal->vertex3f[1][0] = v1[0];
11806         decal->vertex3f[1][1] = v1[1];
11807         decal->vertex3f[1][2] = v1[2];
11808         decal->vertex3f[2][0] = v2[0];
11809         decal->vertex3f[2][1] = v2[1];
11810         decal->vertex3f[2][2] = v2[2];
11811         decal->texcoord2f[0][0] = t0[0];
11812         decal->texcoord2f[0][1] = t0[1];
11813         decal->texcoord2f[1][0] = t1[0];
11814         decal->texcoord2f[1][1] = t1[1];
11815         decal->texcoord2f[2][0] = t2[0];
11816         decal->texcoord2f[2][1] = t2[1];
11817         TriangleNormal(v0, v1, v2, decal->plane);
11818         VectorNormalize(decal->plane);
11819         decal->plane[3] = DotProduct(v0, decal->plane);
11820 }
11821
11822 extern cvar_t cl_decals_bias;
11823 extern cvar_t cl_decals_models;
11824 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11825 // baseparms, parms, temps
11826 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)
11827 {
11828         int cornerindex;
11829         int index;
11830         float v[9][3];
11831         const float *vertex3f;
11832         const float *normal3f;
11833         int numpoints;
11834         float points[2][9][3];
11835         float temp[3];
11836         float tc[9][2];
11837         float f;
11838         float c[9][4];
11839         const int *e;
11840
11841         e = rsurface.modelelement3i + 3*triangleindex;
11842
11843         vertex3f = rsurface.modelvertex3f;
11844         normal3f = rsurface.modelnormal3f;
11845
11846         if (normal3f)
11847         {
11848                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11849                 {
11850                         index = 3*e[cornerindex];
11851                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11852                 }
11853         }
11854         else
11855         {
11856                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11857                 {
11858                         index = 3*e[cornerindex];
11859                         VectorCopy(vertex3f + index, v[cornerindex]);
11860                 }
11861         }
11862
11863         // cull backfaces
11864         //TriangleNormal(v[0], v[1], v[2], normal);
11865         //if (DotProduct(normal, localnormal) < 0.0f)
11866         //      continue;
11867         // clip by each of the box planes formed from the projection matrix
11868         // if anything survives, we emit the decal
11869         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]);
11870         if (numpoints < 3)
11871                 return;
11872         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]);
11873         if (numpoints < 3)
11874                 return;
11875         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]);
11876         if (numpoints < 3)
11877                 return;
11878         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]);
11879         if (numpoints < 3)
11880                 return;
11881         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]);
11882         if (numpoints < 3)
11883                 return;
11884         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]);
11885         if (numpoints < 3)
11886                 return;
11887         // some part of the triangle survived, so we have to accept it...
11888         if (dynamic)
11889         {
11890                 // dynamic always uses the original triangle
11891                 numpoints = 3;
11892                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11893                 {
11894                         index = 3*e[cornerindex];
11895                         VectorCopy(vertex3f + index, v[cornerindex]);
11896                 }
11897         }
11898         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11899         {
11900                 // convert vertex positions to texcoords
11901                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11902                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11903                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11904                 // calculate distance fade from the projection origin
11905                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11906                 f = bound(0.0f, f, 1.0f);
11907                 c[cornerindex][0] = r * f;
11908                 c[cornerindex][1] = g * f;
11909                 c[cornerindex][2] = b * f;
11910                 c[cornerindex][3] = 1.0f;
11911                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11912         }
11913         if (dynamic)
11914                 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);
11915         else
11916                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11917                         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);
11918 }
11919 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)
11920 {
11921         matrix4x4_t projection;
11922         decalsystem_t *decalsystem;
11923         qboolean dynamic;
11924         dp_model_t *model;
11925         const msurface_t *surface;
11926         const msurface_t *surfaces;
11927         const int *surfacelist;
11928         const texture_t *texture;
11929         int numtriangles;
11930         int numsurfacelist;
11931         int surfacelistindex;
11932         int surfaceindex;
11933         int triangleindex;
11934         float localorigin[3];
11935         float localnormal[3];
11936         float localmins[3];
11937         float localmaxs[3];
11938         float localsize;
11939         //float normal[3];
11940         float planes[6][4];
11941         float angles[3];
11942         bih_t *bih;
11943         int bih_triangles_count;
11944         int bih_triangles[256];
11945         int bih_surfaces[256];
11946
11947         decalsystem = &ent->decalsystem;
11948         model = ent->model;
11949         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11950         {
11951                 R_DecalSystem_Reset(&ent->decalsystem);
11952                 return;
11953         }
11954
11955         if (!model->brush.data_leafs && !cl_decals_models.integer)
11956         {
11957                 if (decalsystem->model)
11958                         R_DecalSystem_Reset(decalsystem);
11959                 return;
11960         }
11961
11962         if (decalsystem->model != model)
11963                 R_DecalSystem_Reset(decalsystem);
11964         decalsystem->model = model;
11965
11966         RSurf_ActiveModelEntity(ent, true, false, false);
11967
11968         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11969         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11970         VectorNormalize(localnormal);
11971         localsize = worldsize*rsurface.inversematrixscale;
11972         localmins[0] = localorigin[0] - localsize;
11973         localmins[1] = localorigin[1] - localsize;
11974         localmins[2] = localorigin[2] - localsize;
11975         localmaxs[0] = localorigin[0] + localsize;
11976         localmaxs[1] = localorigin[1] + localsize;
11977         localmaxs[2] = localorigin[2] + localsize;
11978
11979         //VectorCopy(localnormal, planes[4]);
11980         //VectorVectors(planes[4], planes[2], planes[0]);
11981         AnglesFromVectors(angles, localnormal, NULL, false);
11982         AngleVectors(angles, planes[0], planes[2], planes[4]);
11983         VectorNegate(planes[0], planes[1]);
11984         VectorNegate(planes[2], planes[3]);
11985         VectorNegate(planes[4], planes[5]);
11986         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11987         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11988         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11989         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11990         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11991         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11992
11993 #if 1
11994 // works
11995 {
11996         matrix4x4_t forwardprojection;
11997         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11998         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11999 }
12000 #else
12001 // broken
12002 {
12003         float projectionvector[4][3];
12004         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12005         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12006         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12007         projectionvector[0][0] = planes[0][0] * ilocalsize;
12008         projectionvector[0][1] = planes[1][0] * ilocalsize;
12009         projectionvector[0][2] = planes[2][0] * ilocalsize;
12010         projectionvector[1][0] = planes[0][1] * ilocalsize;
12011         projectionvector[1][1] = planes[1][1] * ilocalsize;
12012         projectionvector[1][2] = planes[2][1] * ilocalsize;
12013         projectionvector[2][0] = planes[0][2] * ilocalsize;
12014         projectionvector[2][1] = planes[1][2] * ilocalsize;
12015         projectionvector[2][2] = planes[2][2] * ilocalsize;
12016         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12017         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12018         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12019         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12020 }
12021 #endif
12022
12023         dynamic = model->surfmesh.isanimated;
12024         numsurfacelist = model->nummodelsurfaces;
12025         surfacelist = model->sortedmodelsurfaces;
12026         surfaces = model->data_surfaces;
12027
12028         bih = NULL;
12029         bih_triangles_count = -1;
12030         if(!dynamic)
12031         {
12032                 if(model->render_bih.numleafs)
12033                         bih = &model->render_bih;
12034                 else if(model->collision_bih.numleafs)
12035                         bih = &model->collision_bih;
12036         }
12037         if(bih)
12038                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12039         if(bih_triangles_count == 0)
12040                 return;
12041         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12042                 return;
12043         if(bih_triangles_count > 0)
12044         {
12045                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12046                 {
12047                         surfaceindex = bih_surfaces[triangleindex];
12048                         surface = surfaces + surfaceindex;
12049                         texture = surface->texture;
12050                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12051                                 continue;
12052                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12053                                 continue;
12054                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12055                 }
12056         }
12057         else
12058         {
12059                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12060                 {
12061                         surfaceindex = surfacelist[surfacelistindex];
12062                         surface = surfaces + surfaceindex;
12063                         // check cull box first because it rejects more than any other check
12064                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12065                                 continue;
12066                         // skip transparent surfaces
12067                         texture = surface->texture;
12068                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12069                                 continue;
12070                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12071                                 continue;
12072                         numtriangles = surface->num_triangles;
12073                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12074                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12075                 }
12076         }
12077 }
12078
12079 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12080 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)
12081 {
12082         int renderentityindex;
12083         float worldmins[3];
12084         float worldmaxs[3];
12085         entity_render_t *ent;
12086
12087         if (!cl_decals_newsystem.integer)
12088                 return;
12089
12090         worldmins[0] = worldorigin[0] - worldsize;
12091         worldmins[1] = worldorigin[1] - worldsize;
12092         worldmins[2] = worldorigin[2] - worldsize;
12093         worldmaxs[0] = worldorigin[0] + worldsize;
12094         worldmaxs[1] = worldorigin[1] + worldsize;
12095         worldmaxs[2] = worldorigin[2] + worldsize;
12096
12097         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12098
12099         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12100         {
12101                 ent = r_refdef.scene.entities[renderentityindex];
12102                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12103                         continue;
12104
12105                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12106         }
12107 }
12108
12109 typedef struct r_decalsystem_splatqueue_s
12110 {
12111         vec3_t worldorigin;
12112         vec3_t worldnormal;
12113         float color[4];
12114         float tcrange[4];
12115         float worldsize;
12116         unsigned int decalsequence;
12117 }
12118 r_decalsystem_splatqueue_t;
12119
12120 int r_decalsystem_numqueued = 0;
12121 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12122
12123 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)
12124 {
12125         r_decalsystem_splatqueue_t *queue;
12126
12127         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12128                 return;
12129
12130         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12131         VectorCopy(worldorigin, queue->worldorigin);
12132         VectorCopy(worldnormal, queue->worldnormal);
12133         Vector4Set(queue->color, r, g, b, a);
12134         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12135         queue->worldsize = worldsize;
12136         queue->decalsequence = cl.decalsequence++;
12137 }
12138
12139 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12140 {
12141         int i;
12142         r_decalsystem_splatqueue_t *queue;
12143
12144         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12145                 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);
12146         r_decalsystem_numqueued = 0;
12147 }
12148
12149 extern cvar_t cl_decals_max;
12150 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12151 {
12152         int i;
12153         decalsystem_t *decalsystem = &ent->decalsystem;
12154         int numdecals;
12155         unsigned int killsequence;
12156         tridecal_t *decal;
12157         float frametime;
12158         float lifetime;
12159
12160         if (!decalsystem->numdecals)
12161                 return;
12162
12163         if (r_showsurfaces.integer)
12164                 return;
12165
12166         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12167         {
12168                 R_DecalSystem_Reset(decalsystem);
12169                 return;
12170         }
12171
12172         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12173         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12174
12175         if (decalsystem->lastupdatetime)
12176                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12177         else
12178                 frametime = 0;
12179         decalsystem->lastupdatetime = r_refdef.scene.time;
12180         numdecals = decalsystem->numdecals;
12181
12182         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12183         {
12184                 if (decal->color4f[0][3])
12185                 {
12186                         decal->lived += frametime;
12187                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12188                         {
12189                                 memset(decal, 0, sizeof(*decal));
12190                                 if (decalsystem->freedecal > i)
12191                                         decalsystem->freedecal = i;
12192                         }
12193                 }
12194         }
12195         decal = decalsystem->decals;
12196         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12197                 numdecals--;
12198
12199         // collapse the array by shuffling the tail decals into the gaps
12200         for (;;)
12201         {
12202                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12203                         decalsystem->freedecal++;
12204                 if (decalsystem->freedecal == numdecals)
12205                         break;
12206                 decal[decalsystem->freedecal] = decal[--numdecals];
12207         }
12208
12209         decalsystem->numdecals = numdecals;
12210
12211         if (numdecals <= 0)
12212         {
12213                 // if there are no decals left, reset decalsystem
12214                 R_DecalSystem_Reset(decalsystem);
12215         }
12216 }
12217
12218 extern skinframe_t *decalskinframe;
12219 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12220 {
12221         int i;
12222         decalsystem_t *decalsystem = &ent->decalsystem;
12223         int numdecals;
12224         tridecal_t *decal;
12225         float faderate;
12226         float alpha;
12227         float *v3f;
12228         float *c4f;
12229         float *t2f;
12230         const int *e;
12231         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12232         int numtris = 0;
12233
12234         numdecals = decalsystem->numdecals;
12235         if (!numdecals)
12236                 return;
12237
12238         if (r_showsurfaces.integer)
12239                 return;
12240
12241         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12242         {
12243                 R_DecalSystem_Reset(decalsystem);
12244                 return;
12245         }
12246
12247         // if the model is static it doesn't matter what value we give for
12248         // wantnormals and wanttangents, so this logic uses only rules applicable
12249         // to a model, knowing that they are meaningless otherwise
12250         if (ent == r_refdef.scene.worldentity)
12251                 RSurf_ActiveWorldEntity();
12252         else
12253                 RSurf_ActiveModelEntity(ent, false, false, false);
12254
12255         decalsystem->lastupdatetime = r_refdef.scene.time;
12256
12257         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12258
12259         // update vertex positions for animated models
12260         v3f = decalsystem->vertex3f;
12261         c4f = decalsystem->color4f;
12262         t2f = decalsystem->texcoord2f;
12263         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12264         {
12265                 if (!decal->color4f[0][3])
12266                         continue;
12267
12268                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12269                         continue;
12270
12271                 // skip backfaces
12272                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12273                         continue;
12274
12275                 // update color values for fading decals
12276                 if (decal->lived >= cl_decals_time.value)
12277                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12278                 else
12279                         alpha = 1.0f;
12280
12281                 c4f[ 0] = decal->color4f[0][0] * alpha;
12282                 c4f[ 1] = decal->color4f[0][1] * alpha;
12283                 c4f[ 2] = decal->color4f[0][2] * alpha;
12284                 c4f[ 3] = 1;
12285                 c4f[ 4] = decal->color4f[1][0] * alpha;
12286                 c4f[ 5] = decal->color4f[1][1] * alpha;
12287                 c4f[ 6] = decal->color4f[1][2] * alpha;
12288                 c4f[ 7] = 1;
12289                 c4f[ 8] = decal->color4f[2][0] * alpha;
12290                 c4f[ 9] = decal->color4f[2][1] * alpha;
12291                 c4f[10] = decal->color4f[2][2] * alpha;
12292                 c4f[11] = 1;
12293
12294                 t2f[0] = decal->texcoord2f[0][0];
12295                 t2f[1] = decal->texcoord2f[0][1];
12296                 t2f[2] = decal->texcoord2f[1][0];
12297                 t2f[3] = decal->texcoord2f[1][1];
12298                 t2f[4] = decal->texcoord2f[2][0];
12299                 t2f[5] = decal->texcoord2f[2][1];
12300
12301                 // update vertex positions for animated models
12302                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12303                 {
12304                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12305                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12306                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12307                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12308                 }
12309                 else
12310                 {
12311                         VectorCopy(decal->vertex3f[0], v3f);
12312                         VectorCopy(decal->vertex3f[1], v3f + 3);
12313                         VectorCopy(decal->vertex3f[2], v3f + 6);
12314                 }
12315
12316                 if (r_refdef.fogenabled)
12317                 {
12318                         alpha = RSurf_FogVertex(v3f);
12319                         VectorScale(c4f, alpha, c4f);
12320                         alpha = RSurf_FogVertex(v3f + 3);
12321                         VectorScale(c4f + 4, alpha, c4f + 4);
12322                         alpha = RSurf_FogVertex(v3f + 6);
12323                         VectorScale(c4f + 8, alpha, c4f + 8);
12324                 }
12325
12326                 v3f += 9;
12327                 c4f += 12;
12328                 t2f += 6;
12329                 numtris++;
12330         }
12331
12332         if (numtris > 0)
12333         {
12334                 r_refdef.stats[r_stat_drawndecals] += numtris;
12335
12336                 // now render the decals all at once
12337                 // (this assumes they all use one particle font texture!)
12338                 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);
12339 //              R_Mesh_ResetTextureState();
12340                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12341                 GL_DepthMask(false);
12342                 GL_DepthRange(0, 1);
12343                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12344                 GL_DepthTest(true);
12345                 GL_CullFace(GL_NONE);
12346                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12347                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12348                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12349         }
12350 }
12351
12352 static void R_DrawModelDecals(void)
12353 {
12354         int i, numdecals;
12355
12356         // fade faster when there are too many decals
12357         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12358         for (i = 0;i < r_refdef.scene.numentities;i++)
12359                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12360
12361         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12362         for (i = 0;i < r_refdef.scene.numentities;i++)
12363                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12364                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12365
12366         R_DecalSystem_ApplySplatEntitiesQueue();
12367
12368         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12369         for (i = 0;i < r_refdef.scene.numentities;i++)
12370                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12371
12372         r_refdef.stats[r_stat_totaldecals] += numdecals;
12373
12374         if (r_showsurfaces.integer)
12375                 return;
12376
12377         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12378
12379         for (i = 0;i < r_refdef.scene.numentities;i++)
12380         {
12381                 if (!r_refdef.viewcache.entityvisible[i])
12382                         continue;
12383                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12384                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12385         }
12386 }
12387
12388 extern cvar_t mod_collision_bih;
12389 static void R_DrawDebugModel(void)
12390 {
12391         entity_render_t *ent = rsurface.entity;
12392         int i, j, flagsmask;
12393         const msurface_t *surface;
12394         dp_model_t *model = ent->model;
12395
12396         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12397                 return;
12398
12399         if (r_showoverdraw.value > 0)
12400         {
12401                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12402                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12403                 R_SetupShader_Generic_NoTexture(false, false);
12404                 GL_DepthTest(false);
12405                 GL_DepthMask(false);
12406                 GL_DepthRange(0, 1);
12407                 GL_BlendFunc(GL_ONE, GL_ONE);
12408                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12409                 {
12410                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12411                                 continue;
12412                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12413                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12414                         {
12415                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12416                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12417                                 if (!rsurface.texture->currentlayers->depthmask)
12418                                         GL_Color(c, 0, 0, 1.0f);
12419                                 else if (ent == r_refdef.scene.worldentity)
12420                                         GL_Color(c, c, c, 1.0f);
12421                                 else
12422                                         GL_Color(0, c, 0, 1.0f);
12423                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12424                                 RSurf_DrawBatch();
12425                         }
12426                 }
12427                 rsurface.texture = NULL;
12428         }
12429
12430         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12431
12432 //      R_Mesh_ResetTextureState();
12433         R_SetupShader_Generic_NoTexture(false, false);
12434         GL_DepthRange(0, 1);
12435         GL_DepthTest(!r_showdisabledepthtest.integer);
12436         GL_DepthMask(false);
12437         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12438
12439         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12440         {
12441                 int triangleindex;
12442                 int bihleafindex;
12443                 qboolean cullbox = false;
12444                 const q3mbrush_t *brush;
12445                 const bih_t *bih = &model->collision_bih;
12446                 const bih_leaf_t *bihleaf;
12447                 float vertex3f[3][3];
12448                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12449                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12450                 {
12451                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12452                                 continue;
12453                         switch (bihleaf->type)
12454                         {
12455                         case BIH_BRUSH:
12456                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12457                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12458                                 {
12459                                         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);
12460                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12461                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12462                                 }
12463                                 break;
12464                         case BIH_COLLISIONTRIANGLE:
12465                                 triangleindex = bihleaf->itemindex;
12466                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12467                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12468                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12469                                 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);
12470                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12471                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12472                                 break;
12473                         case BIH_RENDERTRIANGLE:
12474                                 triangleindex = bihleaf->itemindex;
12475                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12476                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12477                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12478                                 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);
12479                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12480                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12481                                 break;
12482                         }
12483                 }
12484         }
12485
12486         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12487
12488 #ifndef USE_GLES2
12489         if (r_showtris.integer && qglPolygonMode)
12490         {
12491                 if (r_showdisabledepthtest.integer)
12492                 {
12493                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12494                         GL_DepthMask(false);
12495                 }
12496                 else
12497                 {
12498                         GL_BlendFunc(GL_ONE, GL_ZERO);
12499                         GL_DepthMask(true);
12500                 }
12501                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12502                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12503                 {
12504                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12505                                 continue;
12506                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12507                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12508                         {
12509                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12510                                 if (!rsurface.texture->currentlayers->depthmask)
12511                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12512                                 else if (ent == r_refdef.scene.worldentity)
12513                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12514                                 else
12515                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12516                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12517                                 RSurf_DrawBatch();
12518                         }
12519                 }
12520                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12521                 rsurface.texture = NULL;
12522         }
12523
12524         if (r_shownormals.value != 0 && qglBegin)
12525         {
12526                 int l, k;
12527                 vec3_t v;
12528                 if (r_showdisabledepthtest.integer)
12529                 {
12530                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12531                         GL_DepthMask(false);
12532                 }
12533                 else
12534                 {
12535                         GL_BlendFunc(GL_ONE, GL_ZERO);
12536                         GL_DepthMask(true);
12537                 }
12538                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12539                 {
12540                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12541                                 continue;
12542                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12543                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12544                         {
12545                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12546                                 qglBegin(GL_LINES);
12547                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12548                                 {
12549                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12550                                         {
12551                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12552                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12553                                                 qglVertex3f(v[0], v[1], v[2]);
12554                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12555                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12556                                                 qglVertex3f(v[0], v[1], v[2]);
12557                                         }
12558                                 }
12559                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12560                                 {
12561                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12562                                         {
12563                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12564                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12565                                                 qglVertex3f(v[0], v[1], v[2]);
12566                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12567                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12568                                                 qglVertex3f(v[0], v[1], v[2]);
12569                                         }
12570                                 }
12571                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12572                                 {
12573                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12574                                         {
12575                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12576                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12577                                                 qglVertex3f(v[0], v[1], v[2]);
12578                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12579                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12580                                                 qglVertex3f(v[0], v[1], v[2]);
12581                                         }
12582                                 }
12583                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12584                                 {
12585                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12586                                         {
12587                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12588                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12589                                                 qglVertex3f(v[0], v[1], v[2]);
12590                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12591                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12592                                                 qglVertex3f(v[0], v[1], v[2]);
12593                                         }
12594                                 }
12595                                 qglEnd();
12596                                 CHECKGLERROR
12597                         }
12598                 }
12599                 rsurface.texture = NULL;
12600         }
12601 #endif
12602 }
12603
12604 int r_maxsurfacelist = 0;
12605 const msurface_t **r_surfacelist = NULL;
12606 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12607 {
12608         int i, j, endj, flagsmask;
12609         dp_model_t *model = r_refdef.scene.worldmodel;
12610         msurface_t *surfaces;
12611         unsigned char *update;
12612         int numsurfacelist = 0;
12613         if (model == NULL)
12614                 return;
12615
12616         if (r_maxsurfacelist < model->num_surfaces)
12617         {
12618                 r_maxsurfacelist = model->num_surfaces;
12619                 if (r_surfacelist)
12620                         Mem_Free((msurface_t**)r_surfacelist);
12621                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12622         }
12623
12624         RSurf_ActiveWorldEntity();
12625
12626         surfaces = model->data_surfaces;
12627         update = model->brushq1.lightmapupdateflags;
12628
12629         // update light styles on this submodel
12630         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12631         {
12632                 model_brush_lightstyleinfo_t *style;
12633                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12634                 {
12635                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12636                         {
12637                                 int *list = style->surfacelist;
12638                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12639                                 for (j = 0;j < style->numsurfaces;j++)
12640                                         update[list[j]] = true;
12641                         }
12642                 }
12643         }
12644
12645         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12646
12647         if (debug)
12648         {
12649                 R_DrawDebugModel();
12650                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12651                 return;
12652         }
12653
12654         rsurface.lightmaptexture = NULL;
12655         rsurface.deluxemaptexture = NULL;
12656         rsurface.uselightmaptexture = false;
12657         rsurface.texture = NULL;
12658         rsurface.rtlight = NULL;
12659         numsurfacelist = 0;
12660         // add visible surfaces to draw list
12661         for (i = 0;i < model->nummodelsurfaces;i++)
12662         {
12663                 j = model->sortedmodelsurfaces[i];
12664                 if (r_refdef.viewcache.world_surfacevisible[j])
12665                         r_surfacelist[numsurfacelist++] = surfaces + j;
12666         }
12667         // update lightmaps if needed
12668         if (model->brushq1.firstrender)
12669         {
12670                 model->brushq1.firstrender = false;
12671                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12672                         if (update[j])
12673                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12674         }
12675         else if (update)
12676         {
12677                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12678                         if (r_refdef.viewcache.world_surfacevisible[j])
12679                                 if (update[j])
12680                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12681         }
12682         // don't do anything if there were no surfaces
12683         if (!numsurfacelist)
12684         {
12685                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12686                 return;
12687         }
12688         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12689
12690         // add to stats if desired
12691         if (r_speeds.integer && !skysurfaces && !depthonly)
12692         {
12693                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12694                 for (j = 0;j < numsurfacelist;j++)
12695                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12696         }
12697
12698         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12699 }
12700
12701 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12702 {
12703         int i, j, endj, flagsmask;
12704         dp_model_t *model = ent->model;
12705         msurface_t *surfaces;
12706         unsigned char *update;
12707         int numsurfacelist = 0;
12708         if (model == NULL)
12709                 return;
12710
12711         if (r_maxsurfacelist < model->num_surfaces)
12712         {
12713                 r_maxsurfacelist = model->num_surfaces;
12714                 if (r_surfacelist)
12715                         Mem_Free((msurface_t **)r_surfacelist);
12716                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12717         }
12718
12719         // if the model is static it doesn't matter what value we give for
12720         // wantnormals and wanttangents, so this logic uses only rules applicable
12721         // to a model, knowing that they are meaningless otherwise
12722         if (ent == r_refdef.scene.worldentity)
12723                 RSurf_ActiveWorldEntity();
12724         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12725                 RSurf_ActiveModelEntity(ent, false, false, false);
12726         else if (prepass)
12727                 RSurf_ActiveModelEntity(ent, true, true, true);
12728         else if (depthonly)
12729         {
12730                 switch (vid.renderpath)
12731                 {
12732                 case RENDERPATH_GL20:
12733                 case RENDERPATH_D3D9:
12734                 case RENDERPATH_D3D10:
12735                 case RENDERPATH_D3D11:
12736                 case RENDERPATH_SOFT:
12737                 case RENDERPATH_GLES2:
12738                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12739                         break;
12740                 case RENDERPATH_GL11:
12741                 case RENDERPATH_GL13:
12742                 case RENDERPATH_GLES1:
12743                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12744                         break;
12745                 }
12746         }
12747         else
12748         {
12749                 switch (vid.renderpath)
12750                 {
12751                 case RENDERPATH_GL20:
12752                 case RENDERPATH_D3D9:
12753                 case RENDERPATH_D3D10:
12754                 case RENDERPATH_D3D11:
12755                 case RENDERPATH_SOFT:
12756                 case RENDERPATH_GLES2:
12757                         RSurf_ActiveModelEntity(ent, true, true, false);
12758                         break;
12759                 case RENDERPATH_GL11:
12760                 case RENDERPATH_GL13:
12761                 case RENDERPATH_GLES1:
12762                         RSurf_ActiveModelEntity(ent, true, false, false);
12763                         break;
12764                 }
12765         }
12766
12767         surfaces = model->data_surfaces;
12768         update = model->brushq1.lightmapupdateflags;
12769
12770         // update light styles
12771         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12772         {
12773                 model_brush_lightstyleinfo_t *style;
12774                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12775                 {
12776                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12777                         {
12778                                 int *list = style->surfacelist;
12779                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12780                                 for (j = 0;j < style->numsurfaces;j++)
12781                                         update[list[j]] = true;
12782                         }
12783                 }
12784         }
12785
12786         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12787
12788         if (debug)
12789         {
12790                 R_DrawDebugModel();
12791                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12792                 return;
12793         }
12794
12795         rsurface.lightmaptexture = NULL;
12796         rsurface.deluxemaptexture = NULL;
12797         rsurface.uselightmaptexture = false;
12798         rsurface.texture = NULL;
12799         rsurface.rtlight = NULL;
12800         numsurfacelist = 0;
12801         // add visible surfaces to draw list
12802         for (i = 0;i < model->nummodelsurfaces;i++)
12803                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12804         // don't do anything if there were no surfaces
12805         if (!numsurfacelist)
12806         {
12807                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12808                 return;
12809         }
12810         // update lightmaps if needed
12811         if (update)
12812         {
12813                 int updated = 0;
12814                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12815                 {
12816                         if (update[j])
12817                         {
12818                                 updated++;
12819                                 R_BuildLightMap(ent, surfaces + j);
12820                         }
12821                 }
12822         }
12823
12824         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12825
12826         // add to stats if desired
12827         if (r_speeds.integer && !skysurfaces && !depthonly)
12828         {
12829                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12830                 for (j = 0;j < numsurfacelist;j++)
12831                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12832         }
12833
12834         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12835 }
12836
12837 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12838 {
12839         static texture_t texture;
12840         static msurface_t surface;
12841         const msurface_t *surfacelist = &surface;
12842
12843         // fake enough texture and surface state to render this geometry
12844
12845         texture.update_lastrenderframe = -1; // regenerate this texture
12846         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12847         texture.basealpha = 1.0f;
12848         texture.currentskinframe = skinframe;
12849         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12850         texture.offsetmapping = OFFSETMAPPING_OFF;
12851         texture.offsetscale = 1;
12852         texture.specularscalemod = 1;
12853         texture.specularpowermod = 1;
12854         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12855         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12856         // JUST GREP FOR "specularscalemod = 1".
12857
12858         surface.texture = &texture;
12859         surface.num_triangles = numtriangles;
12860         surface.num_firsttriangle = firsttriangle;
12861         surface.num_vertices = numvertices;
12862         surface.num_firstvertex = firstvertex;
12863
12864         // now render it
12865         rsurface.texture = R_GetCurrentTexture(surface.texture);
12866         rsurface.lightmaptexture = NULL;
12867         rsurface.deluxemaptexture = NULL;
12868         rsurface.uselightmaptexture = false;
12869         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12870 }
12871
12872 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)
12873 {
12874         static msurface_t surface;
12875         const msurface_t *surfacelist = &surface;
12876
12877         // fake enough texture and surface state to render this geometry
12878         surface.texture = texture;
12879         surface.num_triangles = numtriangles;
12880         surface.num_firsttriangle = firsttriangle;
12881         surface.num_vertices = numvertices;
12882         surface.num_firstvertex = firstvertex;
12883
12884         // now render it
12885         rsurface.texture = R_GetCurrentTexture(surface.texture);
12886         rsurface.lightmaptexture = NULL;
12887         rsurface.deluxemaptexture = NULL;
12888         rsurface.uselightmaptexture = false;
12889         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12890 }