]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Rework R_CanSeeBox a bit to support an eyejitter feature, and make it available throu...
[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_sortentities);
4363         Cvar_RegisterVariable(&r_drawviewmodel);
4364         Cvar_RegisterVariable(&r_drawexteriormodel);
4365         Cvar_RegisterVariable(&r_speeds);
4366         Cvar_RegisterVariable(&r_fullbrights);
4367         Cvar_RegisterVariable(&r_wateralpha);
4368         Cvar_RegisterVariable(&r_dynamic);
4369         Cvar_RegisterVariable(&r_fakelight);
4370         Cvar_RegisterVariable(&r_fakelight_intensity);
4371         Cvar_RegisterVariable(&r_fullbright);
4372         Cvar_RegisterVariable(&r_shadows);
4373         Cvar_RegisterVariable(&r_shadows_darken);
4374         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4375         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4376         Cvar_RegisterVariable(&r_shadows_throwdistance);
4377         Cvar_RegisterVariable(&r_shadows_throwdirection);
4378         Cvar_RegisterVariable(&r_shadows_focus);
4379         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4380         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4381         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4382         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4383         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4384         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4385         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4386         Cvar_RegisterVariable(&r_fog_exp2);
4387         Cvar_RegisterVariable(&r_fog_clear);
4388         Cvar_RegisterVariable(&r_drawfog);
4389         Cvar_RegisterVariable(&r_transparentdepthmasking);
4390         Cvar_RegisterVariable(&r_transparent_sortmindist);
4391         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4392         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4393         Cvar_RegisterVariable(&r_texture_dds_load);
4394         Cvar_RegisterVariable(&r_texture_dds_save);
4395         Cvar_RegisterVariable(&r_textureunits);
4396         Cvar_RegisterVariable(&gl_combine);
4397         Cvar_RegisterVariable(&r_usedepthtextures);
4398         Cvar_RegisterVariable(&r_viewfbo);
4399         Cvar_RegisterVariable(&r_viewscale);
4400         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4401         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4402         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4403         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4404         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4405         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4406         Cvar_RegisterVariable(&r_glsl);
4407         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4408         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4409         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4410         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4411         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4412         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4413         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4414         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4415         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4416         Cvar_RegisterVariable(&r_glsl_postprocess);
4417         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4418         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4419         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4420         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4421         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4422         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4423         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4424         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4425         Cvar_RegisterVariable(&r_celshading);
4426         Cvar_RegisterVariable(&r_celoutlines);
4427
4428         Cvar_RegisterVariable(&r_water);
4429         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4430         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4431         Cvar_RegisterVariable(&r_water_clippingplanebias);
4432         Cvar_RegisterVariable(&r_water_refractdistort);
4433         Cvar_RegisterVariable(&r_water_reflectdistort);
4434         Cvar_RegisterVariable(&r_water_scissormode);
4435         Cvar_RegisterVariable(&r_water_lowquality);
4436         Cvar_RegisterVariable(&r_water_hideplayer);
4437         Cvar_RegisterVariable(&r_water_fbo);
4438
4439         Cvar_RegisterVariable(&r_lerpsprites);
4440         Cvar_RegisterVariable(&r_lerpmodels);
4441         Cvar_RegisterVariable(&r_lerplightstyles);
4442         Cvar_RegisterVariable(&r_waterscroll);
4443         Cvar_RegisterVariable(&r_bloom);
4444         Cvar_RegisterVariable(&r_bloom_colorscale);
4445         Cvar_RegisterVariable(&r_bloom_brighten);
4446         Cvar_RegisterVariable(&r_bloom_blur);
4447         Cvar_RegisterVariable(&r_bloom_resolution);
4448         Cvar_RegisterVariable(&r_bloom_colorexponent);
4449         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4450         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4451         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4452         Cvar_RegisterVariable(&r_hdr_glowintensity);
4453         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4454         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4455         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4456         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4457         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4458         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4459         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4460         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4461         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4462         Cvar_RegisterVariable(&developer_texturelogging);
4463         Cvar_RegisterVariable(&gl_lightmaps);
4464         Cvar_RegisterVariable(&r_test);
4465         Cvar_RegisterVariable(&r_batch_multidraw);
4466         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4467         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4468         Cvar_RegisterVariable(&r_glsl_skeletal);
4469         Cvar_RegisterVariable(&r_glsl_saturation);
4470         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4471         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4472         Cvar_RegisterVariable(&r_framedatasize);
4473         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4474                 Cvar_RegisterVariable(&r_buffermegs[i]);
4475         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4476         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4477                 Cvar_SetValue("r_fullbrights", 0);
4478 #ifdef DP_MOBILETOUCH
4479         // GLES devices have terrible depth precision in general, so...
4480         Cvar_SetValueQuick(&r_nearclip, 4);
4481         Cvar_SetValueQuick(&r_farclip_base, 4096);
4482         Cvar_SetValueQuick(&r_farclip_world, 0);
4483         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4484 #endif
4485         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4486 }
4487
4488 void Render_Init(void)
4489 {
4490         gl_backend_init();
4491         R_Textures_Init();
4492         GL_Main_Init();
4493         Font_Init();
4494         GL_Draw_Init();
4495         R_Shadow_Init();
4496         R_Sky_Init();
4497         GL_Surf_Init();
4498         Sbar_Init();
4499         R_Particles_Init();
4500         R_Explosion_Init();
4501         R_LightningBeams_Init();
4502         Mod_RenderInit();
4503 }
4504
4505 /*
4506 ===============
4507 GL_Init
4508 ===============
4509 */
4510 #ifndef USE_GLES2
4511 extern char *ENGINE_EXTENSIONS;
4512 void GL_Init (void)
4513 {
4514         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4515         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4516         gl_version = (const char *)qglGetString(GL_VERSION);
4517         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4518
4519         if (!gl_extensions)
4520                 gl_extensions = "";
4521         if (!gl_platformextensions)
4522                 gl_platformextensions = "";
4523
4524         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4525         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4526         Con_Printf("GL_VERSION: %s\n", gl_version);
4527         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4528         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4529
4530         VID_CheckExtensions();
4531
4532         // LordHavoc: report supported extensions
4533 #ifdef CONFIG_MENU
4534         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4535 #else
4536         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4537 #endif
4538
4539         // clear to black (loading plaque will be seen over this)
4540         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4541 }
4542 #endif
4543
4544 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4545 {
4546         int i;
4547         mplane_t *p;
4548         if (r_trippy.integer)
4549                 return false;
4550         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4551         {
4552                 p = r_refdef.view.frustum + i;
4553                 switch(p->signbits)
4554                 {
4555                 default:
4556                 case 0:
4557                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4558                                 return true;
4559                         break;
4560                 case 1:
4561                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4562                                 return true;
4563                         break;
4564                 case 2:
4565                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4566                                 return true;
4567                         break;
4568                 case 3:
4569                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4570                                 return true;
4571                         break;
4572                 case 4:
4573                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4574                                 return true;
4575                         break;
4576                 case 5:
4577                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4578                                 return true;
4579                         break;
4580                 case 6:
4581                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4582                                 return true;
4583                         break;
4584                 case 7:
4585                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4586                                 return true;
4587                         break;
4588                 }
4589         }
4590         return false;
4591 }
4592
4593 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4594 {
4595         int i;
4596         const mplane_t *p;
4597         if (r_trippy.integer)
4598                 return false;
4599         for (i = 0;i < numplanes;i++)
4600         {
4601                 p = planes + i;
4602                 switch(p->signbits)
4603                 {
4604                 default:
4605                 case 0:
4606                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4607                                 return true;
4608                         break;
4609                 case 1:
4610                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4611                                 return true;
4612                         break;
4613                 case 2:
4614                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4615                                 return true;
4616                         break;
4617                 case 3:
4618                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4619                                 return true;
4620                         break;
4621                 case 4:
4622                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4623                                 return true;
4624                         break;
4625                 case 5:
4626                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4627                                 return true;
4628                         break;
4629                 case 6:
4630                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4631                                 return true;
4632                         break;
4633                 case 7:
4634                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4635                                 return true;
4636                         break;
4637                 }
4638         }
4639         return false;
4640 }
4641
4642 //==================================================================================
4643
4644 // LordHavoc: this stores temporary data used within the same frame
4645
4646 typedef struct r_framedata_mem_s
4647 {
4648         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4649         size_t size; // how much usable space
4650         size_t current; // how much space in use
4651         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4652         size_t wantedsize; // how much space was allocated
4653         unsigned char *data; // start of real data (16byte aligned)
4654 }
4655 r_framedata_mem_t;
4656
4657 static r_framedata_mem_t *r_framedata_mem;
4658
4659 void R_FrameData_Reset(void)
4660 {
4661         while (r_framedata_mem)
4662         {
4663                 r_framedata_mem_t *next = r_framedata_mem->purge;
4664                 Mem_Free(r_framedata_mem);
4665                 r_framedata_mem = next;
4666         }
4667 }
4668
4669 static void R_FrameData_Resize(qboolean mustgrow)
4670 {
4671         size_t wantedsize;
4672         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4673         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4674         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4675         {
4676                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4677                 newmem->wantedsize = wantedsize;
4678                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4679                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4680                 newmem->current = 0;
4681                 newmem->mark = 0;
4682                 newmem->purge = r_framedata_mem;
4683                 r_framedata_mem = newmem;
4684         }
4685 }
4686
4687 void R_FrameData_NewFrame(void)
4688 {
4689         R_FrameData_Resize(false);
4690         if (!r_framedata_mem)
4691                 return;
4692         // if we ran out of space on the last frame, free the old memory now
4693         while (r_framedata_mem->purge)
4694         {
4695                 // repeatedly remove the second item in the list, leaving only head
4696                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4697                 Mem_Free(r_framedata_mem->purge);
4698                 r_framedata_mem->purge = next;
4699         }
4700         // reset the current mem pointer
4701         r_framedata_mem->current = 0;
4702         r_framedata_mem->mark = 0;
4703 }
4704
4705 void *R_FrameData_Alloc(size_t size)
4706 {
4707         void *data;
4708         float newvalue;
4709
4710         // align to 16 byte boundary - the data pointer is already aligned, so we
4711         // only need to ensure the size of every allocation is also aligned
4712         size = (size + 15) & ~15;
4713
4714         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4715         {
4716                 // emergency - we ran out of space, allocate more memory
4717                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4718                 newvalue = r_framedatasize.value * 2.0f;
4719                 // 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
4720                 if (sizeof(size_t) >= 8)
4721                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4722                 else
4723                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4724                 // this might not be a growing it, but we'll allocate another buffer every time
4725                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4726                 R_FrameData_Resize(true);
4727         }
4728
4729         data = r_framedata_mem->data + r_framedata_mem->current;
4730         r_framedata_mem->current += size;
4731
4732         // count the usage for stats
4733         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4734         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4735
4736         return (void *)data;
4737 }
4738
4739 void *R_FrameData_Store(size_t size, void *data)
4740 {
4741         void *d = R_FrameData_Alloc(size);
4742         if (d && data)
4743                 memcpy(d, data, size);
4744         return d;
4745 }
4746
4747 void R_FrameData_SetMark(void)
4748 {
4749         if (!r_framedata_mem)
4750                 return;
4751         r_framedata_mem->mark = r_framedata_mem->current;
4752 }
4753
4754 void R_FrameData_ReturnToMark(void)
4755 {
4756         if (!r_framedata_mem)
4757                 return;
4758         r_framedata_mem->current = r_framedata_mem->mark;
4759 }
4760
4761 //==================================================================================
4762
4763 // avoid reusing the same buffer objects on consecutive frames
4764 #define R_BUFFERDATA_CYCLE 3
4765
4766 typedef struct r_bufferdata_buffer_s
4767 {
4768         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4769         size_t size; // how much usable space
4770         size_t current; // how much space in use
4771         r_meshbuffer_t *buffer; // the buffer itself
4772 }
4773 r_bufferdata_buffer_t;
4774
4775 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4776 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4777
4778 /// frees all dynamic buffers
4779 void R_BufferData_Reset(void)
4780 {
4781         int cycle, type;
4782         r_bufferdata_buffer_t **p, *mem;
4783         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4784         {
4785                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4786                 {
4787                         // free all buffers
4788                         p = &r_bufferdata_buffer[cycle][type];
4789                         while (*p)
4790                         {
4791                                 mem = *p;
4792                                 *p = (*p)->purge;
4793                                 if (mem->buffer)
4794                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4795                                 Mem_Free(mem);
4796                         }
4797                 }
4798         }
4799 }
4800
4801 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4802 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4803 {
4804         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4805         size_t size;
4806         float newvalue = r_buffermegs[type].value;
4807
4808         // increase the cvar if we have to (but only if we already have a mem)
4809         if (mustgrow && mem)
4810                 newvalue *= 2.0f;
4811         newvalue = bound(0.25f, newvalue, 256.0f);
4812         while (newvalue * 1024*1024 < minsize)
4813                 newvalue *= 2.0f;
4814
4815         // clamp the cvar to valid range
4816         newvalue = bound(0.25f, newvalue, 256.0f);
4817         if (r_buffermegs[type].value != newvalue)
4818                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4819
4820         // calculate size in bytes
4821         size = (size_t)(newvalue * 1024*1024);
4822         size = bound(131072, size, 256*1024*1024);
4823
4824         // allocate a new buffer if the size is different (purge old one later)
4825         // or if we were told we must grow the buffer
4826         if (!mem || mem->size != size || mustgrow)
4827         {
4828                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4829                 mem->size = size;
4830                 mem->current = 0;
4831                 if (type == R_BUFFERDATA_VERTEX)
4832                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4833                 else if (type == R_BUFFERDATA_INDEX16)
4834                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4835                 else if (type == R_BUFFERDATA_INDEX32)
4836                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4837                 else if (type == R_BUFFERDATA_UNIFORM)
4838                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4839                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4840                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4841         }
4842 }
4843
4844 void R_BufferData_NewFrame(void)
4845 {
4846         int type;
4847         r_bufferdata_buffer_t **p, *mem;
4848         // cycle to the next frame's buffers
4849         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4850         // if we ran out of space on the last time we used these buffers, free the old memory now
4851         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4852         {
4853                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4854                 {
4855                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4856                         // free all but the head buffer, this is how we recycle obsolete
4857                         // buffers after they are no longer in use
4858                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4859                         while (*p)
4860                         {
4861                                 mem = *p;
4862                                 *p = (*p)->purge;
4863                                 if (mem->buffer)
4864                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4865                                 Mem_Free(mem);
4866                         }
4867                         // reset the current offset
4868                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4869                 }
4870         }
4871 }
4872
4873 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4874 {
4875         r_bufferdata_buffer_t *mem;
4876         int offset = 0;
4877         int padsize;
4878
4879         *returnbufferoffset = 0;
4880
4881         // align size to a byte boundary appropriate for the buffer type, this
4882         // makes all allocations have aligned start offsets
4883         if (type == R_BUFFERDATA_UNIFORM)
4884                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4885         else
4886                 padsize = (datasize + 15) & ~15;
4887
4888         // if we ran out of space in this buffer we must allocate a new one
4889         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)
4890                 R_BufferData_Resize(type, true, padsize);
4891
4892         // if the resize did not give us enough memory, fail
4893         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)
4894                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4895
4896         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4897         offset = (int)mem->current;
4898         mem->current += padsize;
4899
4900         // upload the data to the buffer at the chosen offset
4901         if (offset == 0)
4902                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4903         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4904
4905         // count the usage for stats
4906         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4907         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4908
4909         // return the buffer offset
4910         *returnbufferoffset = offset;
4911
4912         return mem->buffer;
4913 }
4914
4915 //==================================================================================
4916
4917 // LordHavoc: animcache originally written by Echon, rewritten since then
4918
4919 /**
4920  * Animation cache prevents re-generating mesh data for an animated model
4921  * multiple times in one frame for lighting, shadowing, reflections, etc.
4922  */
4923
4924 void R_AnimCache_Free(void)
4925 {
4926 }
4927
4928 void R_AnimCache_ClearCache(void)
4929 {
4930         int i;
4931         entity_render_t *ent;
4932
4933         for (i = 0;i < r_refdef.scene.numentities;i++)
4934         {
4935                 ent = r_refdef.scene.entities[i];
4936                 ent->animcache_vertex3f = NULL;
4937                 ent->animcache_vertex3f_vertexbuffer = NULL;
4938                 ent->animcache_vertex3f_bufferoffset = 0;
4939                 ent->animcache_normal3f = NULL;
4940                 ent->animcache_normal3f_vertexbuffer = NULL;
4941                 ent->animcache_normal3f_bufferoffset = 0;
4942                 ent->animcache_svector3f = NULL;
4943                 ent->animcache_svector3f_vertexbuffer = NULL;
4944                 ent->animcache_svector3f_bufferoffset = 0;
4945                 ent->animcache_tvector3f = NULL;
4946                 ent->animcache_tvector3f_vertexbuffer = NULL;
4947                 ent->animcache_tvector3f_bufferoffset = 0;
4948                 ent->animcache_vertexmesh = NULL;
4949                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4950                 ent->animcache_vertexmesh_bufferoffset = 0;
4951                 ent->animcache_skeletaltransform3x4 = NULL;
4952                 ent->animcache_skeletaltransform3x4buffer = NULL;
4953                 ent->animcache_skeletaltransform3x4offset = 0;
4954                 ent->animcache_skeletaltransform3x4size = 0;
4955         }
4956 }
4957
4958 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4959 {
4960         int i;
4961
4962         // check if we need the meshbuffers
4963         if (!vid.useinterleavedarrays)
4964                 return;
4965
4966         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4967                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4968         // TODO: upload vertexbuffer?
4969         if (ent->animcache_vertexmesh)
4970         {
4971                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4972                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4973                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4974                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4975                 for (i = 0;i < numvertices;i++)
4976                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4977                 if (ent->animcache_svector3f)
4978                         for (i = 0;i < numvertices;i++)
4979                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4980                 if (ent->animcache_tvector3f)
4981                         for (i = 0;i < numvertices;i++)
4982                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4983                 if (ent->animcache_normal3f)
4984                         for (i = 0;i < numvertices;i++)
4985                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4986         }
4987 }
4988
4989 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4990 {
4991         dp_model_t *model = ent->model;
4992         int numvertices;
4993
4994         // see if this ent is worth caching
4995         if (!model || !model->Draw || !model->AnimateVertices)
4996                 return false;
4997         // nothing to cache if it contains no animations and has no skeleton
4998         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4999                 return false;
5000         // see if it is already cached for gpuskeletal
5001         if (ent->animcache_skeletaltransform3x4)
5002                 return false;
5003         // see if it is already cached as a mesh
5004         if (ent->animcache_vertex3f)
5005         {
5006                 // check if we need to add normals or tangents
5007                 if (ent->animcache_normal3f)
5008                         wantnormals = false;
5009                 if (ent->animcache_svector3f)
5010                         wanttangents = false;
5011                 if (!wantnormals && !wanttangents)
5012                         return false;
5013         }
5014
5015         // check which kind of cache we need to generate
5016         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5017         {
5018                 // cache the skeleton so the vertex shader can use it
5019                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5020                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5021                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5022                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5023                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
5024                 // note: this can fail if the buffer is at the grow limit
5025                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5026                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5027         }
5028         else if (ent->animcache_vertex3f)
5029         {
5030                 // mesh was already cached but we may need to add normals/tangents
5031                 // (this only happens with multiple views, reflections, cameras, etc)
5032                 if (wantnormals || wanttangents)
5033                 {
5034                         numvertices = model->surfmesh.num_vertices;
5035                         if (wantnormals)
5036                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5037                         if (wanttangents)
5038                         {
5039                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5040                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5041                         }
5042                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5043                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5044                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5045                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5046                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5047                 }
5048         }
5049         else
5050         {
5051                 // generate mesh cache
5052                 numvertices = model->surfmesh.num_vertices;
5053                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5054                 if (wantnormals)
5055                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5056                 if (wanttangents)
5057                 {
5058                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5059                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5060                 }
5061                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5062                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5063                 if (wantnormals || wanttangents)
5064                 {
5065                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5066                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5067                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5068                 }
5069                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5070                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5071                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5072         }
5073         return true;
5074 }
5075
5076 void R_AnimCache_CacheVisibleEntities(void)
5077 {
5078         int i;
5079         qboolean wantnormals = true;
5080         qboolean wanttangents = !r_showsurfaces.integer;
5081
5082         switch(vid.renderpath)
5083         {
5084         case RENDERPATH_GL20:
5085         case RENDERPATH_D3D9:
5086         case RENDERPATH_D3D10:
5087         case RENDERPATH_D3D11:
5088         case RENDERPATH_GLES2:
5089                 break;
5090         case RENDERPATH_GL11:
5091         case RENDERPATH_GL13:
5092         case RENDERPATH_GLES1:
5093                 wanttangents = false;
5094                 break;
5095         case RENDERPATH_SOFT:
5096                 break;
5097         }
5098
5099         if (r_shownormals.integer)
5100                 wanttangents = wantnormals = true;
5101
5102         // TODO: thread this
5103         // NOTE: R_PrepareRTLights() also caches entities
5104
5105         for (i = 0;i < r_refdef.scene.numentities;i++)
5106                 if (r_refdef.viewcache.entityvisible[i])
5107                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5108 }
5109
5110 //==================================================================================
5111
5112 extern cvar_t r_overheadsprites_pushback;
5113
5114 static void R_View_UpdateEntityLighting (void)
5115 {
5116         int i;
5117         entity_render_t *ent;
5118         vec3_t tempdiffusenormal, avg;
5119         vec_t f, fa, fd, fdd;
5120         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5121
5122         for (i = 0;i < r_refdef.scene.numentities;i++)
5123         {
5124                 ent = r_refdef.scene.entities[i];
5125
5126                 // skip unseen models
5127                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5128                         continue;
5129
5130                 // skip bsp models
5131                 if (ent->model && ent->model == cl.worldmodel)
5132                 {
5133                         // TODO: use modellight for r_ambient settings on world?
5134                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5135                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5136                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5137                         continue;
5138                 }
5139                 
5140                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5141                 {
5142                         // aleady updated by CSQC
5143                         // TODO: force modellight on BSP models in this case?
5144                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5145                 }
5146                 else
5147                 {
5148                         // fetch the lighting from the worldmodel data
5149                         VectorClear(ent->modellight_ambient);
5150                         VectorClear(ent->modellight_diffuse);
5151                         VectorClear(tempdiffusenormal);
5152                         if (ent->flags & RENDER_LIGHT)
5153                         {
5154                                 vec3_t org;
5155                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5156
5157                                 // complete lightning for lit sprites
5158                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5159                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5160                                 {
5161                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5162                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5163                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5164                                 }
5165                                 else
5166                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5167
5168                                 if(ent->flags & RENDER_EQUALIZE)
5169                                 {
5170                                         // first fix up ambient lighting...
5171                                         if(r_equalize_entities_minambient.value > 0)
5172                                         {
5173                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5174                                                 if(fd > 0)
5175                                                 {
5176                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5177                                                         if(fa < r_equalize_entities_minambient.value * fd)
5178                                                         {
5179                                                                 // solve:
5180                                                                 //   fa'/fd' = minambient
5181                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5182                                                                 //   ...
5183                                                                 //   fa' = fd' * minambient
5184                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5185                                                                 //   ...
5186                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5187                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5188                                                                 //   ...
5189                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5190                                                                 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
5191                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5192                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5193                                                         }
5194                                                 }
5195                                         }
5196
5197                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5198                                         {
5199                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5200                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5201                                                 f = fa + 0.25 * fd;
5202                                                 if(f > 0)
5203                                                 {
5204                                                         // adjust brightness and saturation to target
5205                                                         avg[0] = avg[1] = avg[2] = fa / f;
5206                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5207                                                         avg[0] = avg[1] = avg[2] = fd / f;
5208                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5209                                                 }
5210                                         }
5211                                 }
5212                         }
5213                         else // highly rare
5214                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5215                 }
5216
5217                 // move the light direction into modelspace coordinates for lighting code
5218                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5219                 if(VectorLength2(ent->modellight_lightdir) == 0)
5220                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5221                 VectorNormalize(ent->modellight_lightdir);
5222         }
5223 }
5224
5225 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5226 {
5227         int i;
5228         vec3_t eyemins, eyemaxs;
5229         vec3_t boxmins, boxmaxs;
5230         vec3_t start;
5231         vec3_t end;
5232         dp_model_t *model = r_refdef.scene.worldmodel;
5233         static vec3_t positions[] = {
5234                 { 0.5f, 0.5f, 0.5f },
5235                 { 0.0f, 0.0f, 0.0f },
5236                 { 0.0f, 0.0f, 1.0f },
5237                 { 0.0f, 1.0f, 0.0f },
5238                 { 0.0f, 1.0f, 1.0f },
5239                 { 1.0f, 0.0f, 0.0f },
5240                 { 1.0f, 0.0f, 1.0f },
5241                 { 1.0f, 1.0f, 0.0f },
5242                 { 1.0f, 1.0f, 1.0f },
5243         };
5244
5245         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5246         if (numsamples < 0)
5247                 return true;
5248
5249         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5250         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5251                 return true;
5252
5253         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5254                 return true;
5255
5256         // expand the eye box a little
5257         eyemins[0] = eye[0] - eyejitter;
5258         eyemaxs[0] = eye[0] + eyejitter;
5259         eyemins[1] = eye[1] - eyejitter;
5260         eyemaxs[1] = eye[1] + eyejitter;
5261         eyemins[2] = eye[2] - eyejitter;
5262         eyemaxs[2] = eye[2] + eyejitter;
5263         // expand the box a little
5264         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5265         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5266         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5267         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5268         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5269         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5270
5271         // return true if eye overlaps enlarged box
5272         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5273                 return true;
5274
5275         // try specific positions in the box first - note that these can be cached
5276         if (r_cullentities_trace_entityocclusion.integer)
5277         {
5278                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5279                 {
5280                         VectorCopy(eye, start);
5281                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5282                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5283                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5284                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5285                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NOMONSTERS, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY);
5286                         // not picky - if the trace ended anywhere in the box we're good
5287                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5288                                 return true;
5289                 }
5290         }
5291         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5292                 return true;
5293
5294         // try various random positions
5295         for (i = 0; i < numsamples; i++)
5296         {
5297                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5298                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5299                 if (r_cullentities_trace_entityocclusion.integer)
5300                 {
5301                         trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5302                         // not picky - if the trace ended anywhere in the box we're good
5303                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5304                                 return true;
5305                 }
5306                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5307                         return true;
5308         }
5309
5310         return false;
5311 }
5312
5313
5314 static void R_View_UpdateEntityVisible (void)
5315 {
5316         int i;
5317         int renderimask;
5318         int samples;
5319         entity_render_t *ent;
5320
5321         if (r_refdef.envmap || r_fb.water.hideplayer)
5322                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5323         else if (chase_active.integer || r_fb.water.renderingscene)
5324                 renderimask = RENDER_VIEWMODEL;
5325         else
5326                 renderimask = RENDER_EXTERIORMODEL;
5327         if (!r_drawviewmodel.integer)
5328                 renderimask |= RENDER_VIEWMODEL;
5329         if (!r_drawexteriormodel.integer)
5330                 renderimask |= RENDER_EXTERIORMODEL;
5331         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5332         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5333         {
5334                 // worldmodel can check visibility
5335                 for (i = 0;i < r_refdef.scene.numentities;i++)
5336                 {
5337                         ent = r_refdef.scene.entities[i];
5338                         if (!(ent->flags & renderimask))
5339                         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)))
5340                         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))
5341                                 r_refdef.viewcache.entityvisible[i] = true;
5342                 }
5343         }
5344         else
5345         {
5346                 // no worldmodel or it can't check visibility
5347                 for (i = 0;i < r_refdef.scene.numentities;i++)
5348                 {
5349                         ent = r_refdef.scene.entities[i];
5350                         if (!(ent->flags & renderimask))
5351                         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)))
5352                                 r_refdef.viewcache.entityvisible[i] = true;
5353                 }
5354         }
5355         if (r_cullentities_trace.integer)
5356         {
5357                 for (i = 0;i < r_refdef.scene.numentities;i++)
5358                 {
5359                         if (!r_refdef.viewcache.entityvisible[i])
5360                                 continue;
5361                         ent = r_refdef.scene.entities[i];
5362                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5363                         {
5364                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5365                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5366                                         ent->last_trace_visibility = realtime;
5367                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5368                                         r_refdef.viewcache.entityvisible[i] = 0;
5369                         }
5370                 }
5371         }
5372 }
5373
5374 /// only used if skyrendermasked, and normally returns false
5375 static int R_DrawBrushModelsSky (void)
5376 {
5377         int i, sky;
5378         entity_render_t *ent;
5379
5380         sky = false;
5381         for (i = 0;i < r_refdef.scene.numentities;i++)
5382         {
5383                 if (!r_refdef.viewcache.entityvisible[i])
5384                         continue;
5385                 ent = r_refdef.scene.entities[i];
5386                 if (!ent->model || !ent->model->DrawSky)
5387                         continue;
5388                 ent->model->DrawSky(ent);
5389                 sky = true;
5390         }
5391         return sky;
5392 }
5393
5394 static void R_DrawNoModel(entity_render_t *ent);
5395 static void R_DrawModels(void)
5396 {
5397         int i;
5398         entity_render_t *ent;
5399
5400         for (i = 0;i < r_refdef.scene.numentities;i++)
5401         {
5402                 if (!r_refdef.viewcache.entityvisible[i])
5403                         continue;
5404                 ent = r_refdef.scene.entities[i];
5405                 r_refdef.stats[r_stat_entities]++;
5406                 /*
5407                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5408                 {
5409                         vec3_t f, l, u, o;
5410                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5411                         Con_Printf("R_DrawModels\n");
5412                         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]);
5413                         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);
5414                         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);
5415                 }
5416                 */
5417                 if (ent->model && ent->model->Draw != NULL)
5418                         ent->model->Draw(ent);
5419                 else
5420                         R_DrawNoModel(ent);
5421         }
5422 }
5423
5424 static void R_DrawModelsDepth(void)
5425 {
5426         int i;
5427         entity_render_t *ent;
5428
5429         for (i = 0;i < r_refdef.scene.numentities;i++)
5430         {
5431                 if (!r_refdef.viewcache.entityvisible[i])
5432                         continue;
5433                 ent = r_refdef.scene.entities[i];
5434                 if (ent->model && ent->model->DrawDepth != NULL)
5435                         ent->model->DrawDepth(ent);
5436         }
5437 }
5438
5439 static void R_DrawModelsDebug(void)
5440 {
5441         int i;
5442         entity_render_t *ent;
5443
5444         for (i = 0;i < r_refdef.scene.numentities;i++)
5445         {
5446                 if (!r_refdef.viewcache.entityvisible[i])
5447                         continue;
5448                 ent = r_refdef.scene.entities[i];
5449                 if (ent->model && ent->model->DrawDebug != NULL)
5450                         ent->model->DrawDebug(ent);
5451         }
5452 }
5453
5454 static void R_DrawModelsAddWaterPlanes(void)
5455 {
5456         int i;
5457         entity_render_t *ent;
5458
5459         for (i = 0;i < r_refdef.scene.numentities;i++)
5460         {
5461                 if (!r_refdef.viewcache.entityvisible[i])
5462                         continue;
5463                 ent = r_refdef.scene.entities[i];
5464                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5465                         ent->model->DrawAddWaterPlanes(ent);
5466         }
5467 }
5468
5469 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}};
5470
5471 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5472 {
5473         if (r_hdr_irisadaptation.integer)
5474         {
5475                 vec3_t p;
5476                 vec3_t ambient;
5477                 vec3_t diffuse;
5478                 vec3_t diffusenormal;
5479                 vec3_t forward;
5480                 vec_t brightness = 0.0f;
5481                 vec_t goal;
5482                 vec_t current;
5483                 vec_t d;
5484                 int c;
5485                 VectorCopy(r_refdef.view.forward, forward);
5486                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5487                 {
5488                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5489                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5490                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5491                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5492                         d = DotProduct(forward, diffusenormal);
5493                         brightness += VectorLength(ambient);
5494                         if (d > 0)
5495                                 brightness += d * VectorLength(diffuse);
5496                 }
5497                 brightness *= 1.0f / c;
5498                 brightness += 0.00001f; // make sure it's never zero
5499                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5500                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5501                 current = r_hdr_irisadaptation_value.value;
5502                 if (current < goal)
5503                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5504                 else if (current > goal)
5505                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5506                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5507                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5508         }
5509         else if (r_hdr_irisadaptation_value.value != 1.0f)
5510                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5511 }
5512
5513 static void R_View_SetFrustum(const int *scissor)
5514 {
5515         int i;
5516         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5517         vec3_t forward, left, up, origin, v;
5518
5519         if(scissor)
5520         {
5521                 // flipped x coordinates (because x points left here)
5522                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5523                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5524
5525                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5526                 switch(vid.renderpath)
5527                 {
5528                         case RENDERPATH_D3D9:
5529                         case RENDERPATH_D3D10:
5530                         case RENDERPATH_D3D11:
5531                                 // non-flipped y coordinates
5532                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5533                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5534                                 break;
5535                         case RENDERPATH_SOFT:
5536                         case RENDERPATH_GL11:
5537                         case RENDERPATH_GL13:
5538                         case RENDERPATH_GL20:
5539                         case RENDERPATH_GLES1:
5540                         case RENDERPATH_GLES2:
5541                                 // non-flipped y coordinates
5542                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5543                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5544                                 break;
5545                 }
5546         }
5547
5548         // we can't trust r_refdef.view.forward and friends in reflected scenes
5549         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5550
5551 #if 0
5552         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5553         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5554         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5555         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5556         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5557         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5558         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5559         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5560         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5561         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5562         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5563         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5564 #endif
5565
5566 #if 0
5567         zNear = r_refdef.nearclip;
5568         nudge = 1.0 - 1.0 / (1<<23);
5569         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5570         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5571         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5572         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5573         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5574         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5575         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5576         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5577 #endif
5578
5579
5580
5581 #if 0
5582         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5583         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5584         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5585         r_refdef.view.frustum[0].dist = m[15] - m[12];
5586
5587         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5588         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5589         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5590         r_refdef.view.frustum[1].dist = m[15] + m[12];
5591
5592         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5593         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5594         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5595         r_refdef.view.frustum[2].dist = m[15] - m[13];
5596
5597         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5598         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5599         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5600         r_refdef.view.frustum[3].dist = m[15] + m[13];
5601
5602         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5603         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5604         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5605         r_refdef.view.frustum[4].dist = m[15] - m[14];
5606
5607         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5608         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5609         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5610         r_refdef.view.frustum[5].dist = m[15] + m[14];
5611 #endif
5612
5613         if (r_refdef.view.useperspective)
5614         {
5615                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5616                 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]);
5617                 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]);
5618                 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]);
5619                 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]);
5620
5621                 // then the normals from the corners relative to origin
5622                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5623                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5624                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5625                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5626
5627                 // in a NORMAL view, forward cross left == up
5628                 // in a REFLECTED view, forward cross left == down
5629                 // so our cross products above need to be adjusted for a left handed coordinate system
5630                 CrossProduct(forward, left, v);
5631                 if(DotProduct(v, up) < 0)
5632                 {
5633                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5634                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5635                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5636                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5637                 }
5638
5639                 // Leaving those out was a mistake, those were in the old code, and they
5640                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5641                 // I couldn't reproduce it after adding those normalizations. --blub
5642                 VectorNormalize(r_refdef.view.frustum[0].normal);
5643                 VectorNormalize(r_refdef.view.frustum[1].normal);
5644                 VectorNormalize(r_refdef.view.frustum[2].normal);
5645                 VectorNormalize(r_refdef.view.frustum[3].normal);
5646
5647                 // make the corners absolute
5648                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5649                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5650                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5651                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5652
5653                 // one more normal
5654                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5655
5656                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5657                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5658                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5659                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5660                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5661         }
5662         else
5663         {
5664                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5665                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5666                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5667                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5668                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5669                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5670                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5671                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5672                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5673                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5674         }
5675         r_refdef.view.numfrustumplanes = 5;
5676
5677         if (r_refdef.view.useclipplane)
5678         {
5679                 r_refdef.view.numfrustumplanes = 6;
5680                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5681         }
5682
5683         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5684                 PlaneClassify(r_refdef.view.frustum + i);
5685
5686         // LordHavoc: note to all quake engine coders, Quake had a special case
5687         // for 90 degrees which assumed a square view (wrong), so I removed it,
5688         // Quake2 has it disabled as well.
5689
5690         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5691         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5692         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5693         //PlaneClassify(&frustum[0]);
5694
5695         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5696         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5697         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5698         //PlaneClassify(&frustum[1]);
5699
5700         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5701         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5702         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5703         //PlaneClassify(&frustum[2]);
5704
5705         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5706         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5707         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5708         //PlaneClassify(&frustum[3]);
5709
5710         // nearclip plane
5711         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5712         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5713         //PlaneClassify(&frustum[4]);
5714 }
5715
5716 static void R_View_UpdateWithScissor(const int *myscissor)
5717 {
5718         R_Main_ResizeViewCache();
5719         R_View_SetFrustum(myscissor);
5720         R_View_WorldVisibility(r_refdef.view.useclipplane);
5721         R_View_UpdateEntityVisible();
5722         R_View_UpdateEntityLighting();
5723 }
5724
5725 static void R_View_Update(void)
5726 {
5727         R_Main_ResizeViewCache();
5728         R_View_SetFrustum(NULL);
5729         R_View_WorldVisibility(r_refdef.view.useclipplane);
5730         R_View_UpdateEntityVisible();
5731         R_View_UpdateEntityLighting();
5732 }
5733
5734 float viewscalefpsadjusted = 1.0f;
5735
5736 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5737 {
5738         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5739         scale = bound(0.03125f, scale, 1.0f);
5740         *outwidth = (int)ceil(width * scale);
5741         *outheight = (int)ceil(height * scale);
5742 }
5743
5744 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5745 {
5746         const float *customclipplane = NULL;
5747         float plane[4];
5748         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5749         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5750         {
5751                 // LordHavoc: couldn't figure out how to make this approach the
5752                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5753                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5754                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5755                         dist = r_refdef.view.clipplane.dist;
5756                 plane[0] = r_refdef.view.clipplane.normal[0];
5757                 plane[1] = r_refdef.view.clipplane.normal[1];
5758                 plane[2] = r_refdef.view.clipplane.normal[2];
5759                 plane[3] = -dist;
5760                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5761         }
5762
5763         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5764         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5765
5766         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5767         if (!r_refdef.view.useperspective)
5768                 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);
5769         else if (vid.stencil && r_useinfinitefarclip.integer)
5770                 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);
5771         else
5772                 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);
5773         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5774         R_SetViewport(&r_refdef.view.viewport);
5775         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5776         {
5777                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5778                 float screenplane[4];
5779                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5780                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5781                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5782                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5783                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5784         }
5785 }
5786
5787 void R_EntityMatrix(const matrix4x4_t *matrix)
5788 {
5789         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5790         {
5791                 gl_modelmatrixchanged = false;
5792                 gl_modelmatrix = *matrix;
5793                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5794                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5795                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5796                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5797                 CHECKGLERROR
5798                 switch(vid.renderpath)
5799                 {
5800                 case RENDERPATH_D3D9:
5801 #ifdef SUPPORTD3D
5802                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5803                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5804 #endif
5805                         break;
5806                 case RENDERPATH_D3D10:
5807                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5808                         break;
5809                 case RENDERPATH_D3D11:
5810                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5811                         break;
5812                 case RENDERPATH_GL11:
5813                 case RENDERPATH_GL13:
5814                 case RENDERPATH_GLES1:
5815 #ifndef USE_GLES2
5816                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5817 #endif
5818                         break;
5819                 case RENDERPATH_SOFT:
5820                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5821                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5822                         break;
5823                 case RENDERPATH_GL20:
5824                 case RENDERPATH_GLES2:
5825                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5826                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5827                         break;
5828                 }
5829         }
5830 }
5831
5832 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5833 {
5834         r_viewport_t viewport;
5835
5836         CHECKGLERROR
5837
5838         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5839         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);
5840         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5841         R_SetViewport(&viewport);
5842         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5843         GL_Color(1, 1, 1, 1);
5844         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5845         GL_BlendFunc(GL_ONE, GL_ZERO);
5846         GL_ScissorTest(false);
5847         GL_DepthMask(false);
5848         GL_DepthRange(0, 1);
5849         GL_DepthTest(false);
5850         GL_DepthFunc(GL_LEQUAL);
5851         R_EntityMatrix(&identitymatrix);
5852         R_Mesh_ResetTextureState();
5853         GL_PolygonOffset(0, 0);
5854         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5855         switch(vid.renderpath)
5856         {
5857         case RENDERPATH_GL11:
5858         case RENDERPATH_GL13:
5859         case RENDERPATH_GL20:
5860         case RENDERPATH_GLES1:
5861         case RENDERPATH_GLES2:
5862                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5863                 break;
5864         case RENDERPATH_D3D9:
5865         case RENDERPATH_D3D10:
5866         case RENDERPATH_D3D11:
5867         case RENDERPATH_SOFT:
5868                 break;
5869         }
5870         GL_CullFace(GL_NONE);
5871
5872         CHECKGLERROR
5873 }
5874
5875 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5876 {
5877         DrawQ_Finish();
5878
5879         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5880 }
5881
5882 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5883 {
5884         DrawQ_Finish();
5885
5886         R_SetupView(true, fbo, depthtexture, colortexture);
5887         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5888         GL_Color(1, 1, 1, 1);
5889         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5890         GL_BlendFunc(GL_ONE, GL_ZERO);
5891         GL_ScissorTest(true);
5892         GL_DepthMask(true);
5893         GL_DepthRange(0, 1);
5894         GL_DepthTest(true);
5895         GL_DepthFunc(GL_LEQUAL);
5896         R_EntityMatrix(&identitymatrix);
5897         R_Mesh_ResetTextureState();
5898         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5899         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5900         switch(vid.renderpath)
5901         {
5902         case RENDERPATH_GL11:
5903         case RENDERPATH_GL13:
5904         case RENDERPATH_GL20:
5905         case RENDERPATH_GLES1:
5906         case RENDERPATH_GLES2:
5907                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5908                 break;
5909         case RENDERPATH_D3D9:
5910         case RENDERPATH_D3D10:
5911         case RENDERPATH_D3D11:
5912         case RENDERPATH_SOFT:
5913                 break;
5914         }
5915         GL_CullFace(r_refdef.view.cullface_back);
5916 }
5917
5918 /*
5919 ================
5920 R_RenderView_UpdateViewVectors
5921 ================
5922 */
5923 void R_RenderView_UpdateViewVectors(void)
5924 {
5925         // break apart the view matrix into vectors for various purposes
5926         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5927         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5928         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5929         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5930         // make an inverted copy of the view matrix for tracking sprites
5931         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5932 }
5933
5934 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5935 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5936
5937 static void R_Water_StartFrame(void)
5938 {
5939         int i;
5940         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5941         r_waterstate_waterplane_t *p;
5942         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;
5943
5944         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5945                 return;
5946
5947         switch(vid.renderpath)
5948         {
5949         case RENDERPATH_GL20:
5950         case RENDERPATH_D3D9:
5951         case RENDERPATH_D3D10:
5952         case RENDERPATH_D3D11:
5953         case RENDERPATH_SOFT:
5954         case RENDERPATH_GLES2:
5955                 break;
5956         case RENDERPATH_GL11:
5957         case RENDERPATH_GL13:
5958         case RENDERPATH_GLES1:
5959                 return;
5960         }
5961
5962         // set waterwidth and waterheight to the water resolution that will be
5963         // used (often less than the screen resolution for faster rendering)
5964         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5965
5966         // calculate desired texture sizes
5967         // can't use water if the card does not support the texture size
5968         if (!r_water.integer || r_showsurfaces.integer)
5969                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5970         else if (vid.support.arb_texture_non_power_of_two)
5971         {
5972                 texturewidth = waterwidth;
5973                 textureheight = waterheight;
5974                 camerawidth = waterwidth;
5975                 cameraheight = waterheight;
5976         }
5977         else
5978         {
5979                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5980                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5981                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5982                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5983         }
5984
5985         // allocate textures as needed
5986         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))
5987         {
5988                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5989                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5990                 {
5991                         if (p->texture_refraction)
5992                                 R_FreeTexture(p->texture_refraction);
5993                         p->texture_refraction = NULL;
5994                         if (p->fbo_refraction)
5995                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5996                         p->fbo_refraction = 0;
5997                         if (p->texture_reflection)
5998                                 R_FreeTexture(p->texture_reflection);
5999                         p->texture_reflection = NULL;
6000                         if (p->fbo_reflection)
6001                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
6002                         p->fbo_reflection = 0;
6003                         if (p->texture_camera)
6004                                 R_FreeTexture(p->texture_camera);
6005                         p->texture_camera = NULL;
6006                         if (p->fbo_camera)
6007                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
6008                         p->fbo_camera = 0;
6009                 }
6010                 memset(&r_fb.water, 0, sizeof(r_fb.water));
6011                 r_fb.water.texturewidth = texturewidth;
6012                 r_fb.water.textureheight = textureheight;
6013                 r_fb.water.camerawidth = camerawidth;
6014                 r_fb.water.cameraheight = cameraheight;
6015         }
6016
6017         if (r_fb.water.texturewidth)
6018         {
6019                 int scaledwidth, scaledheight;
6020
6021                 r_fb.water.enabled = true;
6022
6023                 // water resolution is usually reduced
6024                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6025                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6026                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
6027
6028                 // set up variables that will be used in shader setup
6029                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6030                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6031                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6032                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6033         }
6034
6035         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6036         r_fb.water.numwaterplanes = 0;
6037 }
6038
6039 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
6040 {
6041         int planeindex, bestplaneindex, vertexindex;
6042         vec3_t mins, maxs, normal, center, v, n;
6043         vec_t planescore, bestplanescore;
6044         mplane_t plane;
6045         r_waterstate_waterplane_t *p;
6046         texture_t *t = R_GetCurrentTexture(surface->texture);
6047
6048         rsurface.texture = t;
6049         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
6050         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
6051         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
6052                 return;
6053         // average the vertex normals, find the surface bounds (after deformvertexes)
6054         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6055         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6056         VectorCopy(n, normal);
6057         VectorCopy(v, mins);
6058         VectorCopy(v, maxs);
6059         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6060         {
6061                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6062                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6063                 VectorAdd(normal, n, normal);
6064                 mins[0] = min(mins[0], v[0]);
6065                 mins[1] = min(mins[1], v[1]);
6066                 mins[2] = min(mins[2], v[2]);
6067                 maxs[0] = max(maxs[0], v[0]);
6068                 maxs[1] = max(maxs[1], v[1]);
6069                 maxs[2] = max(maxs[2], v[2]);
6070         }
6071         VectorNormalize(normal);
6072         VectorMAM(0.5f, mins, 0.5f, maxs, center);
6073
6074         VectorCopy(normal, plane.normal);
6075         VectorNormalize(plane.normal);
6076         plane.dist = DotProduct(center, plane.normal);
6077         PlaneClassify(&plane);
6078         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6079         {
6080                 // skip backfaces (except if nocullface is set)
6081 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6082 //                      return;
6083                 VectorNegate(plane.normal, plane.normal);
6084                 plane.dist *= -1;
6085                 PlaneClassify(&plane);
6086         }
6087
6088
6089         // find a matching plane if there is one
6090         bestplaneindex = -1;
6091         bestplanescore = 1048576.0f;
6092         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6093         {
6094                 if(p->camera_entity == t->camera_entity)
6095                 {
6096                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6097                         if (bestplaneindex < 0 || bestplanescore > planescore)
6098                         {
6099                                 bestplaneindex = planeindex;
6100                                 bestplanescore = planescore;
6101                         }
6102                 }
6103         }
6104         planeindex = bestplaneindex;
6105
6106         // if this surface does not fit any known plane rendered this frame, add one
6107         if (planeindex < 0 || bestplanescore > 0.001f)
6108         {
6109                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6110                 {
6111                         // store the new plane
6112                         planeindex = r_fb.water.numwaterplanes++;
6113                         p = r_fb.water.waterplanes + planeindex;
6114                         p->plane = plane;
6115                         // clear materialflags and pvs
6116                         p->materialflags = 0;
6117                         p->pvsvalid = false;
6118                         p->camera_entity = t->camera_entity;
6119                         VectorCopy(mins, p->mins);
6120                         VectorCopy(maxs, p->maxs);
6121                 }
6122                 else
6123                 {
6124                         // We're totally screwed.
6125                         return;
6126                 }
6127         }
6128         else
6129         {
6130                 // merge mins/maxs when we're adding this surface to the plane
6131                 p = r_fb.water.waterplanes + planeindex;
6132                 p->mins[0] = min(p->mins[0], mins[0]);
6133                 p->mins[1] = min(p->mins[1], mins[1]);
6134                 p->mins[2] = min(p->mins[2], mins[2]);
6135                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6136                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6137                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6138         }
6139         // merge this surface's materialflags into the waterplane
6140         p->materialflags |= t->currentmaterialflags;
6141         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6142         {
6143                 // merge this surface's PVS into the waterplane
6144                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6145                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6146                 {
6147                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6148                         p->pvsvalid = true;
6149                 }
6150         }
6151 }
6152
6153 extern cvar_t r_drawparticles;
6154 extern cvar_t r_drawdecals;
6155
6156 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6157 {
6158         int myscissor[4];
6159         r_refdef_view_t originalview;
6160         r_refdef_view_t myview;
6161         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;
6162         r_waterstate_waterplane_t *p;
6163         vec3_t visorigin;
6164         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;
6165         char vabuf[1024];
6166
6167         originalview = r_refdef.view;
6168
6169         // lowquality hack, temporarily shut down some cvars and restore afterwards
6170         qualityreduction = r_water_lowquality.integer;
6171         if (qualityreduction > 0)
6172         {
6173                 if (qualityreduction >= 1)
6174                 {
6175                         old_r_shadows = r_shadows.integer;
6176                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6177                         old_r_dlight = r_shadow_realtime_dlight.integer;
6178                         Cvar_SetValueQuick(&r_shadows, 0);
6179                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6180                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6181                 }
6182                 if (qualityreduction >= 2)
6183                 {
6184                         old_r_dynamic = r_dynamic.integer;
6185                         old_r_particles = r_drawparticles.integer;
6186                         old_r_decals = r_drawdecals.integer;
6187                         Cvar_SetValueQuick(&r_dynamic, 0);
6188                         Cvar_SetValueQuick(&r_drawparticles, 0);
6189                         Cvar_SetValueQuick(&r_drawdecals, 0);
6190                 }
6191         }
6192
6193         // make sure enough textures are allocated
6194         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6195         {
6196                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6197                         continue;
6198                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6199                 {
6200                         if (!p->texture_refraction)
6201                                 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);
6202                         if (!p->texture_refraction)
6203                                 goto error;
6204                         if (usewaterfbo)
6205                         {
6206                                 if (r_fb.water.depthtexture == NULL)
6207                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6208                                 if (p->fbo_refraction == 0)
6209                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6210                         }
6211                 }
6212                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6213                 {
6214                         if (!p->texture_camera)
6215                                 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);
6216                         if (!p->texture_camera)
6217                                 goto error;
6218                         if (usewaterfbo)
6219                         {
6220                                 if (r_fb.water.depthtexture == NULL)
6221                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6222                                 if (p->fbo_camera == 0)
6223                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6224                         }
6225                 }
6226
6227                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6228                 {
6229                         if (!p->texture_reflection)
6230                                 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);
6231                         if (!p->texture_reflection)
6232                                 goto error;
6233                         if (usewaterfbo)
6234                         {
6235                                 if (r_fb.water.depthtexture == NULL)
6236                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6237                                 if (p->fbo_reflection == 0)
6238                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6239                         }
6240                 }
6241         }
6242
6243         // render views
6244         r_refdef.view = originalview;
6245         r_refdef.view.showdebug = false;
6246         r_refdef.view.width = r_fb.water.waterwidth;
6247         r_refdef.view.height = r_fb.water.waterheight;
6248         r_refdef.view.useclipplane = true;
6249         myview = r_refdef.view;
6250         r_fb.water.renderingscene = true;
6251         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6252         {
6253                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6254                         continue;
6255                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6256                 {
6257                         r_refdef.view = myview;
6258                         if(r_water_scissormode.integer)
6259                         {
6260                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6261                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6262                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6263                         }
6264
6265                         // render reflected scene and copy into texture
6266                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6267                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6268                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6269                         r_refdef.view.clipplane = p->plane;
6270                         // reverse the cullface settings for this render
6271                         r_refdef.view.cullface_front = GL_FRONT;
6272                         r_refdef.view.cullface_back = GL_BACK;
6273                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6274                         {
6275                                 r_refdef.view.usecustompvs = true;
6276                                 if (p->pvsvalid)
6277                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6278                                 else
6279                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6280                         }
6281
6282                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6283                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6284                         R_ClearScreen(r_refdef.fogenabled);
6285                         if(r_water_scissormode.integer & 2)
6286                                 R_View_UpdateWithScissor(myscissor);
6287                         else
6288                                 R_View_Update();
6289                         R_AnimCache_CacheVisibleEntities();
6290                         if(r_water_scissormode.integer & 1)
6291                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6292                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6293
6294                         if (!p->fbo_reflection)
6295                                 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);
6296                         r_fb.water.hideplayer = false;
6297                 }
6298
6299                 // render the normal view scene and copy into texture
6300                 // (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)
6301                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6302                 {
6303                         r_refdef.view = myview;
6304                         if(r_water_scissormode.integer)
6305                         {
6306                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6307                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6308                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6309                         }
6310
6311                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6312
6313                         r_refdef.view.clipplane = p->plane;
6314                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6315                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6316
6317                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6318                         {
6319                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6320                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6321                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6322                                 R_RenderView_UpdateViewVectors();
6323                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6324                                 {
6325                                         r_refdef.view.usecustompvs = true;
6326                                         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);
6327                                 }
6328                         }
6329
6330                         PlaneClassify(&r_refdef.view.clipplane);
6331
6332                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6333                         R_ClearScreen(r_refdef.fogenabled);
6334                         if(r_water_scissormode.integer & 2)
6335                                 R_View_UpdateWithScissor(myscissor);
6336                         else
6337                                 R_View_Update();
6338                         R_AnimCache_CacheVisibleEntities();
6339                         if(r_water_scissormode.integer & 1)
6340                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6341                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6342
6343                         if (!p->fbo_refraction)
6344                                 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);
6345                         r_fb.water.hideplayer = false;
6346                 }
6347                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6348                 {
6349                         r_refdef.view = myview;
6350
6351                         r_refdef.view.clipplane = p->plane;
6352                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6353                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6354
6355                         r_refdef.view.width = r_fb.water.camerawidth;
6356                         r_refdef.view.height = r_fb.water.cameraheight;
6357                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6358                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6359                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6360                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6361
6362                         if(p->camera_entity)
6363                         {
6364                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6365                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6366                         }
6367
6368                         // note: all of the view is used for displaying... so
6369                         // there is no use in scissoring
6370
6371                         // reverse the cullface settings for this render
6372                         r_refdef.view.cullface_front = GL_FRONT;
6373                         r_refdef.view.cullface_back = GL_BACK;
6374                         // also reverse the view matrix
6375                         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
6376                         R_RenderView_UpdateViewVectors();
6377                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6378                         {
6379                                 r_refdef.view.usecustompvs = true;
6380                                 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);
6381                         }
6382                         
6383                         // camera needs no clipplane
6384                         r_refdef.view.useclipplane = false;
6385
6386                         PlaneClassify(&r_refdef.view.clipplane);
6387
6388                         r_fb.water.hideplayer = false;
6389
6390                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6391                         R_ClearScreen(r_refdef.fogenabled);
6392                         R_View_Update();
6393                         R_AnimCache_CacheVisibleEntities();
6394                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6395
6396                         if (!p->fbo_camera)
6397                                 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);
6398                         r_fb.water.hideplayer = false;
6399                 }
6400
6401         }
6402         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6403         r_fb.water.renderingscene = false;
6404         r_refdef.view = originalview;
6405         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6406         if (!r_fb.water.depthtexture)
6407                 R_ClearScreen(r_refdef.fogenabled);
6408         R_View_Update();
6409         R_AnimCache_CacheVisibleEntities();
6410         goto finish;
6411 error:
6412         r_refdef.view = originalview;
6413         r_fb.water.renderingscene = false;
6414         Cvar_SetValueQuick(&r_water, 0);
6415         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6416 finish:
6417         // lowquality hack, restore cvars
6418         if (qualityreduction > 0)
6419         {
6420                 if (qualityreduction >= 1)
6421                 {
6422                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6423                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6424                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6425                 }
6426                 if (qualityreduction >= 2)
6427                 {
6428                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6429                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6430                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6431                 }
6432         }
6433 }
6434
6435 static void R_Bloom_StartFrame(void)
6436 {
6437         int i;
6438         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6439         int viewwidth, viewheight;
6440         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6441         textype_t textype = TEXTYPE_COLORBUFFER;
6442
6443         switch (vid.renderpath)
6444         {
6445         case RENDERPATH_GL20:
6446                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6447                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6448                 {
6449                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6450                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6451                 }
6452                 break;
6453         case RENDERPATH_GL11:
6454         case RENDERPATH_GL13:
6455         case RENDERPATH_GLES1:
6456         case RENDERPATH_GLES2:
6457         case RENDERPATH_D3D9:
6458         case RENDERPATH_D3D10:
6459         case RENDERPATH_D3D11:
6460                 r_fb.usedepthtextures = false;
6461                 break;
6462         case RENDERPATH_SOFT:
6463                 r_fb.usedepthtextures = true;
6464                 break;
6465         }
6466
6467         if (r_viewscale_fpsscaling.integer)
6468         {
6469                 double actualframetime;
6470                 double targetframetime;
6471                 double adjust;
6472                 actualframetime = r_refdef.lastdrawscreentime;
6473                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6474                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6475                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6476                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6477                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6478                 viewscalefpsadjusted += adjust;
6479                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6480         }
6481         else
6482                 viewscalefpsadjusted = 1.0f;
6483
6484         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6485
6486         switch(vid.renderpath)
6487         {
6488         case RENDERPATH_GL20:
6489         case RENDERPATH_D3D9:
6490         case RENDERPATH_D3D10:
6491         case RENDERPATH_D3D11:
6492         case RENDERPATH_SOFT:
6493         case RENDERPATH_GLES2:
6494                 break;
6495         case RENDERPATH_GL11:
6496         case RENDERPATH_GL13:
6497         case RENDERPATH_GLES1:
6498                 return;
6499         }
6500
6501         // set bloomwidth and bloomheight to the bloom resolution that will be
6502         // used (often less than the screen resolution for faster rendering)
6503         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6504         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6505         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6506         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6507         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6508
6509         // calculate desired texture sizes
6510         if (vid.support.arb_texture_non_power_of_two)
6511         {
6512                 screentexturewidth = vid.width;
6513                 screentextureheight = vid.height;
6514                 bloomtexturewidth = r_fb.bloomwidth;
6515                 bloomtextureheight = r_fb.bloomheight;
6516         }
6517         else
6518         {
6519                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6520                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6521                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6522                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6523         }
6524
6525         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))
6526         {
6527                 Cvar_SetValueQuick(&r_bloom, 0);
6528                 Cvar_SetValueQuick(&r_motionblur, 0);
6529                 Cvar_SetValueQuick(&r_damageblur, 0);
6530         }
6531
6532         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6533          && !r_bloom.integer
6534          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6535          && !useviewfbo
6536          && r_viewscale.value == 1.0f
6537          && !r_viewscale_fpsscaling.integer)
6538                 screentexturewidth = screentextureheight = 0;
6539         if (!r_bloom.integer)
6540                 bloomtexturewidth = bloomtextureheight = 0;
6541
6542         // allocate textures as needed
6543         if (r_fb.screentexturewidth != screentexturewidth
6544          || r_fb.screentextureheight != screentextureheight
6545          || r_fb.bloomtexturewidth != bloomtexturewidth
6546          || r_fb.bloomtextureheight != bloomtextureheight
6547          || r_fb.textype != textype
6548          || useviewfbo != (r_fb.fbo != 0))
6549         {
6550                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6551                 {
6552                         if (r_fb.bloomtexture[i])
6553                                 R_FreeTexture(r_fb.bloomtexture[i]);
6554                         r_fb.bloomtexture[i] = NULL;
6555
6556                         if (r_fb.bloomfbo[i])
6557                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6558                         r_fb.bloomfbo[i] = 0;
6559                 }
6560
6561                 if (r_fb.fbo)
6562                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6563                 r_fb.fbo = 0;
6564
6565                 if (r_fb.colortexture)
6566                         R_FreeTexture(r_fb.colortexture);
6567                 r_fb.colortexture = NULL;
6568
6569                 if (r_fb.depthtexture)
6570                         R_FreeTexture(r_fb.depthtexture);
6571                 r_fb.depthtexture = NULL;
6572
6573                 if (r_fb.ghosttexture)
6574                         R_FreeTexture(r_fb.ghosttexture);
6575                 r_fb.ghosttexture = NULL;
6576
6577                 r_fb.screentexturewidth = screentexturewidth;
6578                 r_fb.screentextureheight = screentextureheight;
6579                 r_fb.bloomtexturewidth = bloomtexturewidth;
6580                 r_fb.bloomtextureheight = bloomtextureheight;
6581                 r_fb.textype = textype;
6582
6583                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6584                 {
6585                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6586                                 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);
6587                         r_fb.ghosttexture_valid = false;
6588                         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);
6589                         if (useviewfbo)
6590                         {
6591                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6592                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6593                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6594                         }
6595                 }
6596
6597                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6598                 {
6599                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6600                         {
6601                                 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);
6602                                 if (useviewfbo)
6603                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6604                         }
6605                 }
6606         }
6607
6608         // bloom texture is a different resolution
6609         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6610         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6611         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6612         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6613         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6614
6615         // set up a texcoord array for the full resolution screen image
6616         // (we have to keep this around to copy back during final render)
6617         r_fb.screentexcoord2f[0] = 0;
6618         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6619         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6620         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6621         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6622         r_fb.screentexcoord2f[5] = 0;
6623         r_fb.screentexcoord2f[6] = 0;
6624         r_fb.screentexcoord2f[7] = 0;
6625
6626         if(r_fb.fbo) 
6627         {
6628                 for (i = 1;i < 8;i += 2)
6629                 {
6630                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6631                 }
6632         }
6633
6634         // set up a texcoord array for the reduced resolution bloom image
6635         // (which will be additive blended over the screen image)
6636         r_fb.bloomtexcoord2f[0] = 0;
6637         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6638         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6639         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6640         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6641         r_fb.bloomtexcoord2f[5] = 0;
6642         r_fb.bloomtexcoord2f[6] = 0;
6643         r_fb.bloomtexcoord2f[7] = 0;
6644
6645         switch(vid.renderpath)
6646         {
6647         case RENDERPATH_GL11:
6648         case RENDERPATH_GL13:
6649         case RENDERPATH_GL20:
6650         case RENDERPATH_SOFT:
6651         case RENDERPATH_GLES1:
6652         case RENDERPATH_GLES2:
6653                 break;
6654         case RENDERPATH_D3D9:
6655         case RENDERPATH_D3D10:
6656         case RENDERPATH_D3D11:
6657                 for (i = 0;i < 4;i++)
6658                 {
6659                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6660                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6661                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6662                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6663                 }
6664                 break;
6665         }
6666
6667         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6668
6669         if (r_fb.fbo)
6670                 r_refdef.view.clear = true;
6671 }
6672
6673 static void R_Bloom_MakeTexture(void)
6674 {
6675         int x, range, dir;
6676         float xoffset, yoffset, r, brighten;
6677         rtexture_t *intex;
6678         float colorscale = r_bloom_colorscale.value;
6679
6680         r_refdef.stats[r_stat_bloom]++;
6681     
6682 #if 0
6683     // this copy is unnecessary since it happens in R_BlendView already
6684         if (!r_fb.fbo)
6685         {
6686                 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);
6687                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6688         }
6689 #endif
6690
6691         // scale down screen texture to the bloom texture size
6692         CHECKGLERROR
6693         r_fb.bloomindex = 0;
6694         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6695         R_SetViewport(&r_fb.bloomviewport);
6696         GL_CullFace(GL_NONE);
6697         GL_DepthTest(false);
6698         GL_BlendFunc(GL_ONE, GL_ZERO);
6699         GL_Color(colorscale, colorscale, colorscale, 1);
6700         // 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...
6701         switch(vid.renderpath)
6702         {
6703         case RENDERPATH_GL11:
6704         case RENDERPATH_GL13:
6705         case RENDERPATH_GL20:
6706         case RENDERPATH_GLES1:
6707         case RENDERPATH_GLES2:
6708         case RENDERPATH_SOFT:
6709                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6710                 break;
6711         case RENDERPATH_D3D9:
6712         case RENDERPATH_D3D10:
6713         case RENDERPATH_D3D11:
6714                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6715                 break;
6716         }
6717         // TODO: do boxfilter scale-down in shader?
6718         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6719         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6720         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6721
6722         // we now have a properly scaled bloom image
6723         if (!r_fb.bloomfbo[r_fb.bloomindex])
6724         {
6725                 // copy it into the bloom texture
6726                 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);
6727                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6728         }
6729
6730         // multiply bloom image by itself as many times as desired
6731         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6732         {
6733                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6734                 r_fb.bloomindex ^= 1;
6735                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6736                 x *= 2;
6737                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6738                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6739                 {
6740                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6741                         GL_Color(r,r,r,1); // apply fix factor
6742                 }
6743                 else
6744                 {
6745                         if(x <= 2)
6746                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6747                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6748                         GL_Color(1,1,1,1); // no fix factor supported here
6749                 }
6750                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6751                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6752                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6753                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6754
6755                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6756                 {
6757                         // copy the darkened image to a texture
6758                         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);
6759                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6760                 }
6761         }
6762
6763         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6764         brighten = r_bloom_brighten.value;
6765         brighten = sqrt(brighten);
6766         if(range >= 1)
6767                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6768
6769         for (dir = 0;dir < 2;dir++)
6770         {
6771                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6772                 r_fb.bloomindex ^= 1;
6773                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6774                 // blend on at multiple vertical offsets to achieve a vertical blur
6775                 // TODO: do offset blends using GLSL
6776                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6777                 GL_BlendFunc(GL_ONE, GL_ZERO);
6778                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6779                 for (x = -range;x <= range;x++)
6780                 {
6781                         if (!dir){xoffset = 0;yoffset = x;}
6782                         else {xoffset = x;yoffset = 0;}
6783                         xoffset /= (float)r_fb.bloomtexturewidth;
6784                         yoffset /= (float)r_fb.bloomtextureheight;
6785                         // compute a texcoord array with the specified x and y offset
6786                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6787                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6788                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6789                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6790                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6791                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6792                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6793                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6794                         // this r value looks like a 'dot' particle, fading sharply to
6795                         // black at the edges
6796                         // (probably not realistic but looks good enough)
6797                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6798                         //r = brighten/(range*2+1);
6799                         r = brighten / (range * 2 + 1);
6800                         if(range >= 1)
6801                                 r *= (1 - x*x/(float)(range*range));
6802                         GL_Color(r, r, r, 1);
6803                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6804                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6805                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6806                         GL_BlendFunc(GL_ONE, GL_ONE);
6807                 }
6808
6809                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6810                 {
6811                         // copy the vertically or horizontally blurred bloom view to a texture
6812                         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);
6813                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6814                 }
6815         }
6816 }
6817
6818 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6819 {
6820         unsigned int permutation;
6821         float uservecs[4][4];
6822
6823         R_EntityMatrix(&identitymatrix);
6824
6825         switch (vid.renderpath)
6826         {
6827         case RENDERPATH_GL20:
6828         case RENDERPATH_D3D9:
6829         case RENDERPATH_D3D10:
6830         case RENDERPATH_D3D11:
6831         case RENDERPATH_SOFT:
6832         case RENDERPATH_GLES2:
6833                 permutation =
6834                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6835                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6836                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6837                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6838                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6839
6840                 if (r_fb.colortexture)
6841                 {
6842                         if (!r_fb.fbo)
6843                         {
6844                                 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);
6845                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6846                         }
6847
6848                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6849                         {
6850                                 // declare variables
6851                                 float blur_factor, blur_mouseaccel, blur_velocity;
6852                                 static float blur_average; 
6853                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6854
6855                                 // set a goal for the factoring
6856                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6857                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6858                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6859                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6860                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6861                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6862
6863                                 // from the goal, pick an averaged value between goal and last value
6864                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6865                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6866
6867                                 // enforce minimum amount of blur 
6868                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6869
6870                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6871
6872                                 // calculate values into a standard alpha
6873                                 cl.motionbluralpha = 1 - exp(-
6874                                                 (
6875                                                  (r_motionblur.value * blur_factor / 80)
6876                                                  +
6877                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6878                                                 )
6879                                                 /
6880                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6881                                           );
6882
6883                                 // randomization for the blur value to combat persistent ghosting
6884                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6885                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6886
6887                                 // apply the blur
6888                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6889                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6890                                 {
6891                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6892                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6893                                         switch(vid.renderpath)
6894                                         {
6895                                         case RENDERPATH_GL11:
6896                                         case RENDERPATH_GL13:
6897                                         case RENDERPATH_GL20:
6898                                         case RENDERPATH_GLES1:
6899                                         case RENDERPATH_GLES2:
6900                                         case RENDERPATH_SOFT:
6901                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6902                                                 break;
6903                                         case RENDERPATH_D3D9:
6904                                         case RENDERPATH_D3D10:
6905                                         case RENDERPATH_D3D11:
6906                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6907                                                 break;
6908                                         }
6909                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6910                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6911                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6912                                 }
6913
6914                                 // updates old view angles for next pass
6915                                 VectorCopy(cl.viewangles, blur_oldangles);
6916
6917                                 // copy view into the ghost texture
6918                                 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);
6919                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6920                                 r_fb.ghosttexture_valid = true;
6921                         }
6922                 }
6923                 else
6924                 {
6925                         // no r_fb.colortexture means we're rendering to the real fb
6926                         // we may still have to do view tint...
6927                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6928                         {
6929                                 // apply a color tint to the whole view
6930                                 R_ResetViewRendering2D(0, NULL, NULL);
6931                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6932                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6933                                 R_SetupShader_Generic_NoTexture(false, true);
6934                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6935                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6936                         }
6937                         break; // no screen processing, no bloom, skip it
6938                 }
6939
6940                 if (r_fb.bloomtexture[0])
6941                 {
6942                         // make the bloom texture
6943                         R_Bloom_MakeTexture();
6944                 }
6945
6946 #if _MSC_VER >= 1400
6947 #define sscanf sscanf_s
6948 #endif
6949                 memset(uservecs, 0, sizeof(uservecs));
6950                 if (r_glsl_postprocess_uservec1_enable.integer)
6951                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6952                 if (r_glsl_postprocess_uservec2_enable.integer)
6953                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6954                 if (r_glsl_postprocess_uservec3_enable.integer)
6955                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6956                 if (r_glsl_postprocess_uservec4_enable.integer)
6957                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6958
6959                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6960                 GL_Color(1, 1, 1, 1);
6961                 GL_BlendFunc(GL_ONE, GL_ZERO);
6962
6963                 switch(vid.renderpath)
6964                 {
6965                 case RENDERPATH_GL20:
6966                 case RENDERPATH_GLES2:
6967                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6968                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6969                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6970                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6971                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6972                         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]);
6973                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6974                         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]);
6975                         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]);
6976                         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]);
6977                         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]);
6978                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6979                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6980                         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);
6981                         break;
6982                 case RENDERPATH_D3D9:
6983 #ifdef SUPPORTD3D
6984                         // 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...
6985                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6986                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6987                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6988                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6989                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6990                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6991                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6992                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6993                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6994                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6995                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6996                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6997                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6998                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6999 #endif
7000                         break;
7001                 case RENDERPATH_D3D10:
7002                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7003                         break;
7004                 case RENDERPATH_D3D11:
7005                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7006                         break;
7007                 case RENDERPATH_SOFT:
7008                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7009                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
7010                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
7011                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
7012                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7013                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7014                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7015                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7016                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7017                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7018                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7019                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
7020                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7021                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7022                         break;
7023                 default:
7024                         break;
7025                 }
7026                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7027                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
7028                 break;
7029         case RENDERPATH_GL11:
7030         case RENDERPATH_GL13:
7031         case RENDERPATH_GLES1:
7032                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7033                 {
7034                         // apply a color tint to the whole view
7035                         R_ResetViewRendering2D(0, NULL, NULL);
7036                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7037                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
7038                         R_SetupShader_Generic_NoTexture(false, true);
7039                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7040                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7041                 }
7042                 break;
7043         }
7044 }
7045
7046 matrix4x4_t r_waterscrollmatrix;
7047
7048 void R_UpdateFog(void)
7049 {
7050         // Nehahra fog
7051         if (gamemode == GAME_NEHAHRA)
7052         {
7053                 if (gl_fogenable.integer)
7054                 {
7055                         r_refdef.oldgl_fogenable = true;
7056                         r_refdef.fog_density = gl_fogdensity.value;
7057                         r_refdef.fog_red = gl_fogred.value;
7058                         r_refdef.fog_green = gl_foggreen.value;
7059                         r_refdef.fog_blue = gl_fogblue.value;
7060                         r_refdef.fog_alpha = 1;
7061                         r_refdef.fog_start = 0;
7062                         r_refdef.fog_end = gl_skyclip.value;
7063                         r_refdef.fog_height = 1<<30;
7064                         r_refdef.fog_fadedepth = 128;
7065                 }
7066                 else if (r_refdef.oldgl_fogenable)
7067                 {
7068                         r_refdef.oldgl_fogenable = false;
7069                         r_refdef.fog_density = 0;
7070                         r_refdef.fog_red = 0;
7071                         r_refdef.fog_green = 0;
7072                         r_refdef.fog_blue = 0;
7073                         r_refdef.fog_alpha = 0;
7074                         r_refdef.fog_start = 0;
7075                         r_refdef.fog_end = 0;
7076                         r_refdef.fog_height = 1<<30;
7077                         r_refdef.fog_fadedepth = 128;
7078                 }
7079         }
7080
7081         // fog parms
7082         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7083         r_refdef.fog_start = max(0, r_refdef.fog_start);
7084         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7085
7086         if (r_refdef.fog_density && r_drawfog.integer)
7087         {
7088                 r_refdef.fogenabled = true;
7089                 // this is the point where the fog reaches 0.9986 alpha, which we
7090                 // consider a good enough cutoff point for the texture
7091                 // (0.9986 * 256 == 255.6)
7092                 if (r_fog_exp2.integer)
7093                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7094                 else
7095                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7096                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7097                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7098                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7099                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7100                         R_BuildFogHeightTexture();
7101                 // fog color was already set
7102                 // update the fog texture
7103                 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)
7104                         R_BuildFogTexture();
7105                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7106                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7107         }
7108         else
7109                 r_refdef.fogenabled = false;
7110
7111         // fog color
7112         if (r_refdef.fog_density)
7113         {
7114                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7115                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7116                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7117
7118                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7119                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7120                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7121                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7122
7123                 {
7124                         vec3_t fogvec;
7125                         VectorCopy(r_refdef.fogcolor, fogvec);
7126                         //   color.rgb *= ContrastBoost * SceneBrightness;
7127                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7128                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7129                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7130                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7131                 }
7132         }
7133 }
7134
7135 void R_UpdateVariables(void)
7136 {
7137         R_Textures_Frame();
7138
7139         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7140
7141         r_refdef.farclip = r_farclip_base.value;
7142         if (r_refdef.scene.worldmodel)
7143                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7144         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7145
7146         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7147                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7148         r_refdef.polygonfactor = 0;
7149         r_refdef.polygonoffset = 0;
7150         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7151         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7152
7153         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7154         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7155         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7156         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7157         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7158         if (FAKELIGHT_ENABLED)
7159         {
7160                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7161         }
7162         else if (r_refdef.scene.worldmodel)
7163         {
7164                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7165         }
7166         if (r_showsurfaces.integer)
7167         {
7168                 r_refdef.scene.rtworld = false;
7169                 r_refdef.scene.rtworldshadows = false;
7170                 r_refdef.scene.rtdlight = false;
7171                 r_refdef.scene.rtdlightshadows = false;
7172                 r_refdef.lightmapintensity = 0;
7173         }
7174
7175         r_gpuskeletal = false;
7176         switch(vid.renderpath)
7177         {
7178         case RENDERPATH_GL20:
7179                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7180         case RENDERPATH_D3D9:
7181         case RENDERPATH_D3D10:
7182         case RENDERPATH_D3D11:
7183         case RENDERPATH_SOFT:
7184         case RENDERPATH_GLES2:
7185                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7186                 {
7187                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7188                         {
7189                                 // build GLSL gamma texture
7190 #define RAMPWIDTH 256
7191                                 unsigned short ramp[RAMPWIDTH * 3];
7192                                 unsigned char rampbgr[RAMPWIDTH][4];
7193                                 int i;
7194
7195                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7196
7197                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7198                                 for(i = 0; i < RAMPWIDTH; ++i)
7199                                 {
7200                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7201                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7202                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7203                                         rampbgr[i][3] = 0;
7204                                 }
7205                                 if (r_texture_gammaramps)
7206                                 {
7207                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7208                                 }
7209                                 else
7210                                 {
7211                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7212                                 }
7213                         }
7214                 }
7215                 else
7216                 {
7217                         // remove GLSL gamma texture
7218                 }
7219                 break;
7220         case RENDERPATH_GL11:
7221         case RENDERPATH_GL13:
7222         case RENDERPATH_GLES1:
7223                 break;
7224         }
7225 }
7226
7227 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7228 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7229 /*
7230 ================
7231 R_SelectScene
7232 ================
7233 */
7234 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7235         if( scenetype != r_currentscenetype ) {
7236                 // store the old scenetype
7237                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7238                 r_currentscenetype = scenetype;
7239                 // move in the new scene
7240                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7241         }
7242 }
7243
7244 /*
7245 ================
7246 R_GetScenePointer
7247 ================
7248 */
7249 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7250 {
7251         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7252         if( scenetype == r_currentscenetype ) {
7253                 return &r_refdef.scene;
7254         } else {
7255                 return &r_scenes_store[ scenetype ];
7256         }
7257 }
7258
7259 static int R_SortEntities_Compare(const void *ap, const void *bp)
7260 {
7261         const entity_render_t *a = *(const entity_render_t **)ap;
7262         const entity_render_t *b = *(const entity_render_t **)bp;
7263
7264         // 1. compare model
7265         if(a->model < b->model)
7266                 return -1;
7267         if(a->model > b->model)
7268                 return +1;
7269
7270         // 2. compare skin
7271         // TODO possibly calculate the REAL skinnum here first using
7272         // skinscenes?
7273         if(a->skinnum < b->skinnum)
7274                 return -1;
7275         if(a->skinnum > b->skinnum)
7276                 return +1;
7277
7278         // everything we compared is equal
7279         return 0;
7280 }
7281 static void R_SortEntities(void)
7282 {
7283         // below or equal 2 ents, sorting never gains anything
7284         if(r_refdef.scene.numentities <= 2)
7285                 return;
7286         // sort
7287         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7288 }
7289
7290 /*
7291 ================
7292 R_RenderView
7293 ================
7294 */
7295 int dpsoftrast_test;
7296 extern cvar_t r_shadow_bouncegrid;
7297 void R_RenderView(void)
7298 {
7299         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7300         int fbo;
7301         rtexture_t *depthtexture;
7302         rtexture_t *colortexture;
7303
7304         dpsoftrast_test = r_test.integer;
7305
7306         if (r_timereport_active)
7307                 R_TimeReport("start");
7308         r_textureframe++; // used only by R_GetCurrentTexture
7309         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7310
7311         if(R_CompileShader_CheckStaticParms())
7312                 R_GLSL_Restart_f();
7313
7314         if (!r_drawentities.integer)
7315                 r_refdef.scene.numentities = 0;
7316         else if (r_sortentities.integer)
7317                 R_SortEntities();
7318
7319         R_AnimCache_ClearCache();
7320
7321         /* adjust for stereo display */
7322         if(R_Stereo_Active())
7323         {
7324                 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);
7325                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7326         }
7327
7328         if (r_refdef.view.isoverlay)
7329         {
7330                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7331                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7332                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7333                 R_TimeReport("depthclear");
7334
7335                 r_refdef.view.showdebug = false;
7336
7337                 r_fb.water.enabled = false;
7338                 r_fb.water.numwaterplanes = 0;
7339
7340                 R_RenderScene(0, NULL, NULL);
7341
7342                 r_refdef.view.matrix = originalmatrix;
7343
7344                 CHECKGLERROR
7345                 return;
7346         }
7347
7348         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7349         {
7350                 r_refdef.view.matrix = originalmatrix;
7351                 return;
7352         }
7353
7354         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7355
7356         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7357                 // in sRGB fallback, behave similar to true sRGB: convert this
7358                 // value from linear to sRGB
7359                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7360
7361         R_RenderView_UpdateViewVectors();
7362
7363         R_Shadow_UpdateWorldLightSelection();
7364
7365         R_Bloom_StartFrame();
7366
7367         // apply bloom brightness offset
7368         if(r_fb.bloomtexture[0])
7369                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7370
7371         R_Water_StartFrame();
7372
7373         // now we probably have an fbo to render into
7374         fbo = r_fb.fbo;
7375         depthtexture = r_fb.depthtexture;
7376         colortexture = r_fb.colortexture;
7377
7378         CHECKGLERROR
7379         if (r_timereport_active)
7380                 R_TimeReport("viewsetup");
7381
7382         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7383
7384         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7385         {
7386                 R_ClearScreen(r_refdef.fogenabled);
7387                 if (r_timereport_active)
7388                         R_TimeReport("viewclear");
7389         }
7390         r_refdef.view.clear = true;
7391
7392         r_refdef.view.showdebug = true;
7393
7394         R_View_Update();
7395         if (r_timereport_active)
7396                 R_TimeReport("visibility");
7397
7398         R_AnimCache_CacheVisibleEntities();
7399         if (r_timereport_active)
7400                 R_TimeReport("animcache");
7401
7402         R_Shadow_UpdateBounceGridTexture();
7403         if (r_timereport_active && r_shadow_bouncegrid.integer)
7404                 R_TimeReport("bouncegrid");
7405
7406         r_fb.water.numwaterplanes = 0;
7407         if (r_fb.water.enabled)
7408                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7409
7410         R_RenderScene(fbo, depthtexture, colortexture);
7411         r_fb.water.numwaterplanes = 0;
7412
7413         R_BlendView(fbo, depthtexture, colortexture);
7414         if (r_timereport_active)
7415                 R_TimeReport("blendview");
7416
7417         GL_Scissor(0, 0, vid.width, vid.height);
7418         GL_ScissorTest(false);
7419
7420         r_refdef.view.matrix = originalmatrix;
7421
7422         CHECKGLERROR
7423 }
7424
7425 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7426 {
7427         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7428         {
7429                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7430                 if (r_timereport_active)
7431                         R_TimeReport("waterworld");
7432         }
7433
7434         // don't let sound skip if going slow
7435         if (r_refdef.scene.extraupdate)
7436                 S_ExtraUpdate ();
7437
7438         R_DrawModelsAddWaterPlanes();
7439         if (r_timereport_active)
7440                 R_TimeReport("watermodels");
7441
7442         if (r_fb.water.numwaterplanes)
7443         {
7444                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7445                 if (r_timereport_active)
7446                         R_TimeReport("waterscenes");
7447         }
7448 }
7449
7450 extern cvar_t cl_locs_show;
7451 static void R_DrawLocs(void);
7452 static void R_DrawEntityBBoxes(void);
7453 static void R_DrawModelDecals(void);
7454 extern cvar_t cl_decals_newsystem;
7455 extern qboolean r_shadow_usingdeferredprepass;
7456 extern int r_shadow_shadowmapatlas_modelshadows_size;
7457 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7458 {
7459         qboolean shadowmapping = false;
7460
7461         if (r_timereport_active)
7462                 R_TimeReport("beginscene");
7463
7464         r_refdef.stats[r_stat_renders]++;
7465
7466         R_UpdateFog();
7467
7468         // don't let sound skip if going slow
7469         if (r_refdef.scene.extraupdate)
7470                 S_ExtraUpdate ();
7471
7472         R_MeshQueue_BeginScene();
7473
7474         R_SkyStartFrame();
7475
7476         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);
7477
7478         if (r_timereport_active)
7479                 R_TimeReport("skystartframe");
7480
7481         if (cl.csqc_vidvars.drawworld)
7482         {
7483                 // don't let sound skip if going slow
7484                 if (r_refdef.scene.extraupdate)
7485                         S_ExtraUpdate ();
7486
7487                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7488                 {
7489                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7490                         if (r_timereport_active)
7491                                 R_TimeReport("worldsky");
7492                 }
7493
7494                 if (R_DrawBrushModelsSky() && r_timereport_active)
7495                         R_TimeReport("bmodelsky");
7496
7497                 if (skyrendermasked && skyrenderlater)
7498                 {
7499                         // we have to force off the water clipping plane while rendering sky
7500                         R_SetupView(false, fbo, depthtexture, colortexture);
7501                         R_Sky();
7502                         R_SetupView(true, fbo, depthtexture, colortexture);
7503                         if (r_timereport_active)
7504                                 R_TimeReport("sky");
7505                 }
7506         }
7507
7508         R_Shadow_PrepareModelShadows();
7509         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7510         if (r_timereport_active)
7511                 R_TimeReport("preparelights");
7512
7513         // render all the shadowmaps that will be used for this view
7514         shadowmapping = R_Shadow_ShadowMappingEnabled();
7515         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7516         {
7517                 R_Shadow_DrawShadowMaps();
7518                 if (r_timereport_active)
7519                         R_TimeReport("shadowmaps");
7520         }
7521
7522         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7523         if (r_shadow_usingdeferredprepass)
7524                 R_Shadow_DrawPrepass();
7525
7526         // now we begin the forward pass of the view render
7527         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7528         {
7529                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7530                 if (r_timereport_active)
7531                         R_TimeReport("worlddepth");
7532         }
7533         if (r_depthfirst.integer >= 2)
7534         {
7535                 R_DrawModelsDepth();
7536                 if (r_timereport_active)
7537                         R_TimeReport("modeldepth");
7538         }
7539
7540         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7541         {
7542                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7543                 if (r_timereport_active)
7544                         R_TimeReport("world");
7545         }
7546
7547         // don't let sound skip if going slow
7548         if (r_refdef.scene.extraupdate)
7549                 S_ExtraUpdate ();
7550
7551         R_DrawModels();
7552         if (r_timereport_active)
7553                 R_TimeReport("models");
7554
7555         // don't let sound skip if going slow
7556         if (r_refdef.scene.extraupdate)
7557                 S_ExtraUpdate ();
7558
7559         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7560         {
7561                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7562                 R_Shadow_DrawModelShadows();
7563                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7564                 // don't let sound skip if going slow
7565                 if (r_refdef.scene.extraupdate)
7566                         S_ExtraUpdate ();
7567         }
7568
7569         if (!r_shadow_usingdeferredprepass)
7570         {
7571                 R_Shadow_DrawLights();
7572                 if (r_timereport_active)
7573                         R_TimeReport("rtlights");
7574         }
7575
7576         // don't let sound skip if going slow
7577         if (r_refdef.scene.extraupdate)
7578                 S_ExtraUpdate ();
7579
7580         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7581         {
7582                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7583                 R_Shadow_DrawModelShadows();
7584                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7585                 // don't let sound skip if going slow
7586                 if (r_refdef.scene.extraupdate)
7587                         S_ExtraUpdate ();
7588         }
7589
7590         if (cl.csqc_vidvars.drawworld)
7591         {
7592                 if (cl_decals_newsystem.integer)
7593                 {
7594                         R_DrawModelDecals();
7595                         if (r_timereport_active)
7596                                 R_TimeReport("modeldecals");
7597                 }
7598                 else
7599                 {
7600                         R_DrawDecals();
7601                         if (r_timereport_active)
7602                                 R_TimeReport("decals");
7603                 }
7604
7605                 R_DrawParticles();
7606                 if (r_timereport_active)
7607                         R_TimeReport("particles");
7608
7609                 R_DrawExplosions();
7610                 if (r_timereport_active)
7611                         R_TimeReport("explosions");
7612
7613                 R_DrawLightningBeams();
7614                 if (r_timereport_active)
7615                         R_TimeReport("lightning");
7616         }
7617
7618         if (cl.csqc_loaded)
7619                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7620
7621         if (r_refdef.view.showdebug)
7622         {
7623                 if (cl_locs_show.integer)
7624                 {
7625                         R_DrawLocs();
7626                         if (r_timereport_active)
7627                                 R_TimeReport("showlocs");
7628                 }
7629
7630                 if (r_drawportals.integer)
7631                 {
7632                         R_DrawPortals();
7633                         if (r_timereport_active)
7634                                 R_TimeReport("portals");
7635                 }
7636
7637                 if (r_showbboxes.value > 0)
7638                 {
7639                         R_DrawEntityBBoxes();
7640                         if (r_timereport_active)
7641                                 R_TimeReport("bboxes");
7642                 }
7643         }
7644
7645         if (r_transparent.integer)
7646         {
7647                 R_MeshQueue_RenderTransparent();
7648                 if (r_timereport_active)
7649                         R_TimeReport("drawtrans");
7650         }
7651
7652         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))
7653         {
7654                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7655                 if (r_timereport_active)
7656                         R_TimeReport("worlddebug");
7657                 R_DrawModelsDebug();
7658                 if (r_timereport_active)
7659                         R_TimeReport("modeldebug");
7660         }
7661
7662         if (cl.csqc_vidvars.drawworld)
7663         {
7664                 R_Shadow_DrawCoronas();
7665                 if (r_timereport_active)
7666                         R_TimeReport("coronas");
7667         }
7668
7669 #if 0
7670         {
7671                 GL_DepthTest(false);
7672                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7673                 GL_Color(1, 1, 1, 1);
7674                 qglBegin(GL_POLYGON);
7675                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7676                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7677                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7678                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7679                 qglEnd();
7680                 qglBegin(GL_POLYGON);
7681                 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]);
7682                 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]);
7683                 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]);
7684                 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]);
7685                 qglEnd();
7686                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7687         }
7688 #endif
7689
7690         // don't let sound skip if going slow
7691         if (r_refdef.scene.extraupdate)
7692                 S_ExtraUpdate ();
7693 }
7694
7695 static const unsigned short bboxelements[36] =
7696 {
7697         5, 1, 3, 5, 3, 7,
7698         6, 2, 0, 6, 0, 4,
7699         7, 3, 2, 7, 2, 6,
7700         4, 0, 1, 4, 1, 5,
7701         4, 5, 7, 4, 7, 6,
7702         1, 0, 2, 1, 2, 3,
7703 };
7704
7705 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7706 {
7707         int i;
7708         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7709
7710         RSurf_ActiveWorldEntity();
7711
7712         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7713         GL_DepthMask(false);
7714         GL_DepthRange(0, 1);
7715         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7716 //      R_Mesh_ResetTextureState();
7717
7718         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7719         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7720         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7721         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7722         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7723         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7724         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7725         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7726         R_FillColors(color4f, 8, cr, cg, cb, ca);
7727         if (r_refdef.fogenabled)
7728         {
7729                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7730                 {
7731                         f1 = RSurf_FogVertex(v);
7732                         f2 = 1 - f1;
7733                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7734                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7735                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7736                 }
7737         }
7738         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7739         R_Mesh_ResetTextureState();
7740         R_SetupShader_Generic_NoTexture(false, false);
7741         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7742 }
7743
7744 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7745 {
7746         prvm_prog_t *prog = SVVM_prog;
7747         int i;
7748         float color[4];
7749         prvm_edict_t *edict;
7750
7751         // this function draws bounding boxes of server entities
7752         if (!sv.active)
7753                 return;
7754
7755         GL_CullFace(GL_NONE);
7756         R_SetupShader_Generic_NoTexture(false, false);
7757
7758         for (i = 0;i < numsurfaces;i++)
7759         {
7760                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7761                 switch ((int)PRVM_serveredictfloat(edict, solid))
7762                 {
7763                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7764                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7765                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7766                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7767                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7768                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7769                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7770                 }
7771                 color[3] *= r_showbboxes.value;
7772                 color[3] = bound(0, color[3], 1);
7773                 GL_DepthTest(!r_showdisabledepthtest.integer);
7774                 GL_CullFace(r_refdef.view.cullface_front);
7775                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7776         }
7777 }
7778
7779 static void R_DrawEntityBBoxes(void)
7780 {
7781         int i;
7782         prvm_edict_t *edict;
7783         vec3_t center;
7784         prvm_prog_t *prog = SVVM_prog;
7785
7786         // this function draws bounding boxes of server entities
7787         if (!sv.active)
7788                 return;
7789
7790         for (i = 0;i < prog->num_edicts;i++)
7791         {
7792                 edict = PRVM_EDICT_NUM(i);
7793                 if (edict->priv.server->free)
7794                         continue;
7795                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7796                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7797                         continue;
7798                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7799                         continue;
7800                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7801                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7802         }
7803 }
7804
7805 static const int nomodelelement3i[24] =
7806 {
7807         5, 2, 0,
7808         5, 1, 2,
7809         5, 0, 3,
7810         5, 3, 1,
7811         0, 2, 4,
7812         2, 1, 4,
7813         3, 0, 4,
7814         1, 3, 4
7815 };
7816
7817 static const unsigned short nomodelelement3s[24] =
7818 {
7819         5, 2, 0,
7820         5, 1, 2,
7821         5, 0, 3,
7822         5, 3, 1,
7823         0, 2, 4,
7824         2, 1, 4,
7825         3, 0, 4,
7826         1, 3, 4
7827 };
7828
7829 static const float nomodelvertex3f[6*3] =
7830 {
7831         -16,   0,   0,
7832          16,   0,   0,
7833           0, -16,   0,
7834           0,  16,   0,
7835           0,   0, -16,
7836           0,   0,  16
7837 };
7838
7839 static const float nomodelcolor4f[6*4] =
7840 {
7841         0.0f, 0.0f, 0.5f, 1.0f,
7842         0.0f, 0.0f, 0.5f, 1.0f,
7843         0.0f, 0.5f, 0.0f, 1.0f,
7844         0.0f, 0.5f, 0.0f, 1.0f,
7845         0.5f, 0.0f, 0.0f, 1.0f,
7846         0.5f, 0.0f, 0.0f, 1.0f
7847 };
7848
7849 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7850 {
7851         int i;
7852         float f1, f2, *c;
7853         float color4f[6*4];
7854
7855         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);
7856
7857         // this is only called once per entity so numsurfaces is always 1, and
7858         // surfacelist is always {0}, so this code does not handle batches
7859
7860         if (rsurface.ent_flags & RENDER_ADDITIVE)
7861         {
7862                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7863                 GL_DepthMask(false);
7864         }
7865         else if (rsurface.colormod[3] < 1)
7866         {
7867                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7868                 GL_DepthMask(false);
7869         }
7870         else
7871         {
7872                 GL_BlendFunc(GL_ONE, GL_ZERO);
7873                 GL_DepthMask(true);
7874         }
7875         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7876         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7877         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7878         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7879         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7880         for (i = 0, c = color4f;i < 6;i++, c += 4)
7881         {
7882                 c[0] *= rsurface.colormod[0];
7883                 c[1] *= rsurface.colormod[1];
7884                 c[2] *= rsurface.colormod[2];
7885                 c[3] *= rsurface.colormod[3];
7886         }
7887         if (r_refdef.fogenabled)
7888         {
7889                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7890                 {
7891                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7892                         f2 = 1 - f1;
7893                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7894                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7895                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7896                 }
7897         }
7898 //      R_Mesh_ResetTextureState();
7899         R_SetupShader_Generic_NoTexture(false, false);
7900         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7901         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7902 }
7903
7904 void R_DrawNoModel(entity_render_t *ent)
7905 {
7906         vec3_t org;
7907         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7908         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7909                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7910         else
7911                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7912 }
7913
7914 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7915 {
7916         vec3_t right1, right2, diff, normal;
7917
7918         VectorSubtract (org2, org1, normal);
7919
7920         // calculate 'right' vector for start
7921         VectorSubtract (r_refdef.view.origin, org1, diff);
7922         CrossProduct (normal, diff, right1);
7923         VectorNormalize (right1);
7924
7925         // calculate 'right' vector for end
7926         VectorSubtract (r_refdef.view.origin, org2, diff);
7927         CrossProduct (normal, diff, right2);
7928         VectorNormalize (right2);
7929
7930         vert[ 0] = org1[0] + width * right1[0];
7931         vert[ 1] = org1[1] + width * right1[1];
7932         vert[ 2] = org1[2] + width * right1[2];
7933         vert[ 3] = org1[0] - width * right1[0];
7934         vert[ 4] = org1[1] - width * right1[1];
7935         vert[ 5] = org1[2] - width * right1[2];
7936         vert[ 6] = org2[0] - width * right2[0];
7937         vert[ 7] = org2[1] - width * right2[1];
7938         vert[ 8] = org2[2] - width * right2[2];
7939         vert[ 9] = org2[0] + width * right2[0];
7940         vert[10] = org2[1] + width * right2[1];
7941         vert[11] = org2[2] + width * right2[2];
7942 }
7943
7944 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)
7945 {
7946         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7947         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7948         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7949         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7950         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7951         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7952         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7953         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7954         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7955         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7956         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7957         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7958 }
7959
7960 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7961 {
7962         int i;
7963         float *vertex3f;
7964         float v[3];
7965         VectorSet(v, x, y, z);
7966         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7967                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7968                         break;
7969         if (i == mesh->numvertices)
7970         {
7971                 if (mesh->numvertices < mesh->maxvertices)
7972                 {
7973                         VectorCopy(v, vertex3f);
7974                         mesh->numvertices++;
7975                 }
7976                 return mesh->numvertices;
7977         }
7978         else
7979                 return i;
7980 }
7981
7982 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7983 {
7984         int i;
7985         int *e, element[3];
7986         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7987         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7988         e = mesh->element3i + mesh->numtriangles * 3;
7989         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7990         {
7991                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7992                 if (mesh->numtriangles < mesh->maxtriangles)
7993                 {
7994                         *e++ = element[0];
7995                         *e++ = element[1];
7996                         *e++ = element[2];
7997                         mesh->numtriangles++;
7998                 }
7999                 element[1] = element[2];
8000         }
8001 }
8002
8003 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8004 {
8005         int i;
8006         int *e, element[3];
8007         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8008         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8009         e = mesh->element3i + mesh->numtriangles * 3;
8010         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8011         {
8012                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8013                 if (mesh->numtriangles < mesh->maxtriangles)
8014                 {
8015                         *e++ = element[0];
8016                         *e++ = element[1];
8017                         *e++ = element[2];
8018                         mesh->numtriangles++;
8019                 }
8020                 element[1] = element[2];
8021         }
8022 }
8023
8024 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8025 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8026 {
8027         int planenum, planenum2;
8028         int w;
8029         int tempnumpoints;
8030         mplane_t *plane, *plane2;
8031         double maxdist;
8032         double temppoints[2][256*3];
8033         // figure out how large a bounding box we need to properly compute this brush
8034         maxdist = 0;
8035         for (w = 0;w < numplanes;w++)
8036                 maxdist = max(maxdist, fabs(planes[w].dist));
8037         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8038         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8039         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8040         {
8041                 w = 0;
8042                 tempnumpoints = 4;
8043                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8044                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8045                 {
8046                         if (planenum2 == planenum)
8047                                 continue;
8048                         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);
8049                         w = !w;
8050                 }
8051                 if (tempnumpoints < 3)
8052                         continue;
8053                 // generate elements forming a triangle fan for this polygon
8054                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8055         }
8056 }
8057
8058 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)
8059 {
8060         texturelayer_t *layer;
8061         layer = t->currentlayers + t->currentnumlayers++;
8062         layer->type = type;
8063         layer->depthmask = depthmask;
8064         layer->blendfunc1 = blendfunc1;
8065         layer->blendfunc2 = blendfunc2;
8066         layer->texture = texture;
8067         layer->texmatrix = *matrix;
8068         layer->color[0] = r;
8069         layer->color[1] = g;
8070         layer->color[2] = b;
8071         layer->color[3] = a;
8072 }
8073
8074 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8075 {
8076         if(parms[0] == 0 && parms[1] == 0)
8077                 return false;
8078         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8079                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8080                         return false;
8081         return true;
8082 }
8083
8084 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8085 {
8086         double index, f;
8087         index = parms[2] + rsurface.shadertime * parms[3];
8088         index -= floor(index);
8089         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8090         {
8091         default:
8092         case Q3WAVEFUNC_NONE:
8093         case Q3WAVEFUNC_NOISE:
8094         case Q3WAVEFUNC_COUNT:
8095                 f = 0;
8096                 break;
8097         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8098         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8099         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8100         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8101         case Q3WAVEFUNC_TRIANGLE:
8102                 index *= 4;
8103                 f = index - floor(index);
8104                 if (index < 1)
8105                 {
8106                         // f = f;
8107                 }
8108                 else if (index < 2)
8109                         f = 1 - f;
8110                 else if (index < 3)
8111                         f = -f;
8112                 else
8113                         f = -(1 - f);
8114                 break;
8115         }
8116         f = parms[0] + parms[1] * f;
8117         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8118                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8119         return (float) f;
8120 }
8121
8122 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8123 {
8124         int w, h, idx;
8125         float shadertime;
8126         float f;
8127         float offsetd[2];
8128         float tcmat[12];
8129         matrix4x4_t matrix, temp;
8130         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8131         // it's better to have one huge fixup every 9 hours than gradual
8132         // degradation over time which looks consistently bad after many hours.
8133         //
8134         // tcmod scroll in particular suffers from this degradation which can't be
8135         // effectively worked around even with floor() tricks because we don't
8136         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8137         // a workaround involving floor() would be incorrect anyway...
8138         shadertime = rsurface.shadertime;
8139         if (shadertime >= 32768.0f)
8140                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8141         switch(tcmod->tcmod)
8142         {
8143                 case Q3TCMOD_COUNT:
8144                 case Q3TCMOD_NONE:
8145                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8146                                 matrix = r_waterscrollmatrix;
8147                         else
8148                                 matrix = identitymatrix;
8149                         break;
8150                 case Q3TCMOD_ENTITYTRANSLATE:
8151                         // this is used in Q3 to allow the gamecode to control texcoord
8152                         // scrolling on the entity, which is not supported in darkplaces yet.
8153                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8154                         break;
8155                 case Q3TCMOD_ROTATE:
8156                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8157                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8158                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8159                         break;
8160                 case Q3TCMOD_SCALE:
8161                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8162                         break;
8163                 case Q3TCMOD_SCROLL:
8164                         // this particular tcmod is a "bug for bug" compatible one with regards to
8165                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8166                         // specifically did the wrapping and so we must mimic that...
8167                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8168                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8169                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8170                         break;
8171                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8172                         w = (int) tcmod->parms[0];
8173                         h = (int) tcmod->parms[1];
8174                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8175                         f = f - floor(f);
8176                         idx = (int) floor(f * w * h);
8177                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8178                         break;
8179                 case Q3TCMOD_STRETCH:
8180                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8181                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8182                         break;
8183                 case Q3TCMOD_TRANSFORM:
8184                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8185                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8186                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8187                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8188                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8189                         break;
8190                 case Q3TCMOD_TURBULENT:
8191                         // this is handled in the RSurf_PrepareVertices function
8192                         matrix = identitymatrix;
8193                         break;
8194         }
8195         temp = *texmatrix;
8196         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8197 }
8198
8199 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8200 {
8201         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8202         char name[MAX_QPATH];
8203         skinframe_t *skinframe;
8204         unsigned char pixels[296*194];
8205         strlcpy(cache->name, skinname, sizeof(cache->name));
8206         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8207         if (developer_loading.integer)
8208                 Con_Printf("loading %s\n", name);
8209         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8210         if (!skinframe || !skinframe->base)
8211         {
8212                 unsigned char *f;
8213                 fs_offset_t filesize;
8214                 skinframe = NULL;
8215                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8216                 if (f)
8217                 {
8218                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8219                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8220                         Mem_Free(f);
8221                 }
8222         }
8223         cache->skinframe = skinframe;
8224 }
8225
8226 texture_t *R_GetCurrentTexture(texture_t *t)
8227 {
8228         int i;
8229         const entity_render_t *ent = rsurface.entity;
8230         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8231         q3shaderinfo_layer_tcmod_t *tcmod;
8232
8233         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8234                 return t->currentframe;
8235         t->update_lastrenderframe = r_textureframe;
8236         t->update_lastrenderentity = (void *)ent;
8237
8238         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8239                 t->camera_entity = ent->entitynumber;
8240         else
8241                 t->camera_entity = 0;
8242
8243         // switch to an alternate material if this is a q1bsp animated material
8244         {
8245                 texture_t *texture = t;
8246                 int s = rsurface.ent_skinnum;
8247                 if ((unsigned int)s >= (unsigned int)model->numskins)
8248                         s = 0;
8249                 if (model->skinscenes)
8250                 {
8251                         if (model->skinscenes[s].framecount > 1)
8252                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8253                         else
8254                                 s = model->skinscenes[s].firstframe;
8255                 }
8256                 if (s > 0)
8257                         t = t + s * model->num_surfaces;
8258                 if (t->animated)
8259                 {
8260                         // use an alternate animation if the entity's frame is not 0,
8261                         // and only if the texture has an alternate animation
8262                         if (t->animated == 2) // q2bsp
8263                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8264                         else if (rsurface.ent_alttextures && t->anim_total[1])
8265                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8266                         else
8267                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8268                 }
8269                 texture->currentframe = t;
8270         }
8271
8272         // update currentskinframe to be a qw skin or animation frame
8273         if (rsurface.ent_qwskin >= 0)
8274         {
8275                 i = rsurface.ent_qwskin;
8276                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8277                 {
8278                         r_qwskincache_size = cl.maxclients;
8279                         if (r_qwskincache)
8280                                 Mem_Free(r_qwskincache);
8281                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8282                 }
8283                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8284                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8285                 t->currentskinframe = r_qwskincache[i].skinframe;
8286                 if (t->materialshaderpass && t->currentskinframe == NULL)
8287                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8288         }
8289         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8290                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8291         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8292                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8293
8294         t->currentmaterialflags = t->basematerialflags;
8295         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8296         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8297                 t->currentalpha *= r_wateralpha.value;
8298         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8299                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8300         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8301                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8302         if (!(rsurface.ent_flags & RENDER_LIGHT))
8303                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8304         else if (FAKELIGHT_ENABLED)
8305         {
8306                 // no modellight if using fakelight for the map
8307         }
8308         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8309         {
8310                 // pick a model lighting mode
8311                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8312                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8313                 else
8314                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8315         }
8316         if (rsurface.ent_flags & RENDER_ADDITIVE)
8317                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8318         else if (t->currentalpha < 1)
8319                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8320         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8321         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8322                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8323         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8324                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8325         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8326                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8327         if (t->backgroundshaderpass)
8328                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8329         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8330         {
8331                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8332                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8333         }
8334         else
8335                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8336         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8337         {
8338                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8339                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8340         }
8341         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8342                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8343
8344         // there is no tcmod
8345         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8346         {
8347                 t->currenttexmatrix = r_waterscrollmatrix;
8348                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8349         }
8350         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8351         {
8352                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8353                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8354         }
8355
8356         if (t->materialshaderpass)
8357                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8358                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8359
8360         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8361         if (t->currentskinframe->qpixels)
8362                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8363         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8364         if (!t->basetexture)
8365                 t->basetexture = r_texture_notexture;
8366         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8367         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8368         t->nmaptexture = t->currentskinframe->nmap;
8369         if (!t->nmaptexture)
8370                 t->nmaptexture = r_texture_blanknormalmap;
8371         t->glosstexture = r_texture_black;
8372         t->glowtexture = t->currentskinframe->glow;
8373         t->fogtexture = t->currentskinframe->fog;
8374         t->reflectmasktexture = t->currentskinframe->reflect;
8375         if (t->backgroundshaderpass)
8376         {
8377                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8378                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8379                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8380                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8381                 t->backgroundglosstexture = r_texture_black;
8382                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8383                 if (!t->backgroundnmaptexture)
8384                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8385                 // make sure that if glow is going to be used, both textures are not NULL
8386                 if (!t->backgroundglowtexture && t->glowtexture)
8387                         t->backgroundglowtexture = r_texture_black;
8388                 if (!t->glowtexture && t->backgroundglowtexture)
8389                         t->glowtexture = r_texture_black;
8390         }
8391         else
8392         {
8393                 t->backgroundbasetexture = r_texture_white;
8394                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8395                 t->backgroundglosstexture = r_texture_black;
8396                 t->backgroundglowtexture = NULL;
8397         }
8398         t->specularpower = r_shadow_glossexponent.value;
8399         // TODO: store reference values for these in the texture?
8400         t->specularscale = 0;
8401         if (r_shadow_gloss.integer > 0)
8402         {
8403                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8404                 {
8405                         if (r_shadow_glossintensity.value > 0)
8406                         {
8407                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8408                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8409                                 t->specularscale = r_shadow_glossintensity.value;
8410                         }
8411                 }
8412                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8413                 {
8414                         t->glosstexture = r_texture_white;
8415                         t->backgroundglosstexture = r_texture_white;
8416                         t->specularscale = r_shadow_gloss2intensity.value;
8417                         t->specularpower = r_shadow_gloss2exponent.value;
8418                 }
8419         }
8420         t->specularscale *= t->specularscalemod;
8421         t->specularpower *= t->specularpowermod;
8422         t->rtlightambient = 0;
8423
8424         // lightmaps mode looks bad with dlights using actual texturing, so turn
8425         // off the colormap and glossmap, but leave the normalmap on as it still
8426         // accurately represents the shading involved
8427         if (gl_lightmaps.integer)
8428         {
8429                 t->basetexture = r_texture_grey128;
8430                 t->pantstexture = r_texture_black;
8431                 t->shirttexture = r_texture_black;
8432                 if (gl_lightmaps.integer < 2)
8433                         t->nmaptexture = r_texture_blanknormalmap;
8434                 t->glosstexture = r_texture_black;
8435                 t->glowtexture = NULL;
8436                 t->fogtexture = NULL;
8437                 t->reflectmasktexture = NULL;
8438                 t->backgroundbasetexture = NULL;
8439                 if (gl_lightmaps.integer < 2)
8440                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8441                 t->backgroundglosstexture = r_texture_black;
8442                 t->backgroundglowtexture = NULL;
8443                 t->specularscale = 0;
8444                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8445         }
8446
8447         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8448         VectorClear(t->dlightcolor);
8449         t->currentnumlayers = 0;
8450         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8451         {
8452                 int blendfunc1, blendfunc2;
8453                 qboolean depthmask;
8454                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8455                 {
8456                         blendfunc1 = GL_SRC_ALPHA;
8457                         blendfunc2 = GL_ONE;
8458                 }
8459                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8460                 {
8461                         blendfunc1 = GL_SRC_ALPHA;
8462                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8463                 }
8464                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8465                 {
8466                         blendfunc1 = t->customblendfunc[0];
8467                         blendfunc2 = t->customblendfunc[1];
8468                 }
8469                 else
8470                 {
8471                         blendfunc1 = GL_ONE;
8472                         blendfunc2 = GL_ZERO;
8473                 }
8474                 // don't colormod evilblend textures
8475                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8476                         VectorSet(t->lightmapcolor, 1, 1, 1);
8477                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8478                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8479                 {
8480                         // fullbright is not affected by r_refdef.lightmapintensity
8481                         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]);
8482                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8483                                 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]);
8484                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8485                                 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]);
8486                 }
8487                 else
8488                 {
8489                         vec3_t ambientcolor;
8490                         float colorscale;
8491                         // set the color tint used for lights affecting this surface
8492                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8493                         colorscale = 2;
8494                         // q3bsp has no lightmap updates, so the lightstylevalue that
8495                         // would normally be baked into the lightmap must be
8496                         // applied to the color
8497                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8498                         if (model->type == mod_brushq3)
8499                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8500                         colorscale *= r_refdef.lightmapintensity;
8501                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8502                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8503                         // basic lit geometry
8504                         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]);
8505                         // add pants/shirt if needed
8506                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8507                                 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]);
8508                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8509                                 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]);
8510                         // now add ambient passes if needed
8511                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8512                         {
8513                                 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]);
8514                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8515                                         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]);
8516                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8517                                         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]);
8518                         }
8519                 }
8520                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8521                         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]);
8522                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8523                 {
8524                         // if this is opaque use alpha blend which will darken the earlier
8525                         // passes cheaply.
8526                         //
8527                         // if this is an alpha blended material, all the earlier passes
8528                         // were darkened by fog already, so we only need to add the fog
8529                         // color ontop through the fog mask texture
8530                         //
8531                         // if this is an additive blended material, all the earlier passes
8532                         // were darkened by fog already, and we should not add fog color
8533                         // (because the background was not darkened, there is no fog color
8534                         // that was lost behind it).
8535                         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]);
8536                 }
8537         }
8538
8539         return t;
8540 }
8541
8542 rsurfacestate_t rsurface;
8543
8544 void RSurf_ActiveWorldEntity(void)
8545 {
8546         dp_model_t *model = r_refdef.scene.worldmodel;
8547         //if (rsurface.entity == r_refdef.scene.worldentity)
8548         //      return;
8549         rsurface.entity = r_refdef.scene.worldentity;
8550         rsurface.skeleton = NULL;
8551         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8552         rsurface.ent_skinnum = 0;
8553         rsurface.ent_qwskin = -1;
8554         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8555         rsurface.shadertime = r_refdef.scene.time;
8556         rsurface.matrix = identitymatrix;
8557         rsurface.inversematrix = identitymatrix;
8558         rsurface.matrixscale = 1;
8559         rsurface.inversematrixscale = 1;
8560         R_EntityMatrix(&identitymatrix);
8561         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8562         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8563         rsurface.fograngerecip = r_refdef.fograngerecip;
8564         rsurface.fogheightfade = r_refdef.fogheightfade;
8565         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8566         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8567         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8568         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8569         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8570         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8571         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8572         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8573         rsurface.colormod[3] = 1;
8574         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);
8575         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8576         rsurface.frameblend[0].lerp = 1;
8577         rsurface.ent_alttextures = false;
8578         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8579         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8580         rsurface.entityskeletaltransform3x4 = NULL;
8581         rsurface.entityskeletaltransform3x4buffer = NULL;
8582         rsurface.entityskeletaltransform3x4offset = 0;
8583         rsurface.entityskeletaltransform3x4size = 0;;
8584         rsurface.entityskeletalnumtransforms = 0;
8585         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8586         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8587         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8588         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8589         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8590         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8591         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8592         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8593         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8594         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8595         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8596         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8597         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8598         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8599         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8600         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8601         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8602         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8603         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8604         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8605         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8606         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8607         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8608         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8609         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8610         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8611         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8612         rsurface.modelelement3i = model->surfmesh.data_element3i;
8613         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8614         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8615         rsurface.modelelement3s = model->surfmesh.data_element3s;
8616         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8617         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8618         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8619         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8620         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8621         rsurface.modelsurfaces = model->data_surfaces;
8622         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8623         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8624         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8625         rsurface.modelgeneratedvertex = false;
8626         rsurface.batchgeneratedvertex = false;
8627         rsurface.batchfirstvertex = 0;
8628         rsurface.batchnumvertices = 0;
8629         rsurface.batchfirsttriangle = 0;
8630         rsurface.batchnumtriangles = 0;
8631         rsurface.batchvertex3f  = NULL;
8632         rsurface.batchvertex3f_vertexbuffer = NULL;
8633         rsurface.batchvertex3f_bufferoffset = 0;
8634         rsurface.batchsvector3f = NULL;
8635         rsurface.batchsvector3f_vertexbuffer = NULL;
8636         rsurface.batchsvector3f_bufferoffset = 0;
8637         rsurface.batchtvector3f = NULL;
8638         rsurface.batchtvector3f_vertexbuffer = NULL;
8639         rsurface.batchtvector3f_bufferoffset = 0;
8640         rsurface.batchnormal3f  = NULL;
8641         rsurface.batchnormal3f_vertexbuffer = NULL;
8642         rsurface.batchnormal3f_bufferoffset = 0;
8643         rsurface.batchlightmapcolor4f = NULL;
8644         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8645         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8646         rsurface.batchtexcoordtexture2f = NULL;
8647         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8648         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8649         rsurface.batchtexcoordlightmap2f = NULL;
8650         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8651         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8652         rsurface.batchskeletalindex4ub = NULL;
8653         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8654         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8655         rsurface.batchskeletalweight4ub = NULL;
8656         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8657         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8658         rsurface.batchvertexmesh = NULL;
8659         rsurface.batchvertexmesh_vertexbuffer = NULL;
8660         rsurface.batchvertexmesh_bufferoffset = 0;
8661         rsurface.batchelement3i = NULL;
8662         rsurface.batchelement3i_indexbuffer = NULL;
8663         rsurface.batchelement3i_bufferoffset = 0;
8664         rsurface.batchelement3s = NULL;
8665         rsurface.batchelement3s_indexbuffer = NULL;
8666         rsurface.batchelement3s_bufferoffset = 0;
8667         rsurface.passcolor4f = NULL;
8668         rsurface.passcolor4f_vertexbuffer = NULL;
8669         rsurface.passcolor4f_bufferoffset = 0;
8670         rsurface.forcecurrenttextureupdate = false;
8671 }
8672
8673 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8674 {
8675         dp_model_t *model = ent->model;
8676         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8677         //      return;
8678         rsurface.entity = (entity_render_t *)ent;
8679         rsurface.skeleton = ent->skeleton;
8680         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8681         rsurface.ent_skinnum = ent->skinnum;
8682         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;
8683         rsurface.ent_flags = ent->flags;
8684         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8685         rsurface.matrix = ent->matrix;
8686         rsurface.inversematrix = ent->inversematrix;
8687         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8688         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8689         R_EntityMatrix(&rsurface.matrix);
8690         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8691         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8692         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8693         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8694         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8695         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8696         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8697         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8698         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8699         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8700         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8701         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8702         rsurface.colormod[3] = ent->alpha;
8703         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8704         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8705         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8706         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8707         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8708         if (ent->model->brush.submodel && !prepass)
8709         {
8710                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8711                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8712         }
8713         // if the animcache code decided it should use the shader path, skip the deform step
8714         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8715         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8716         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8717         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8718         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8719         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8720         {
8721                 if (ent->animcache_vertex3f)
8722                 {
8723                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8724                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8725                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8726                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8727                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8728                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8729                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8730                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8731                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8732                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8733                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8734                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8735                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8736                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8737                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8738                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8739                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8740                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8741                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8742                 }
8743                 else if (wanttangents)
8744                 {
8745                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8746                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8747                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8748                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8749                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8750                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8751                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8752                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8753                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8754                         rsurface.modelvertexmesh = NULL;
8755                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8756                         rsurface.modelvertexmesh_bufferoffset = 0;
8757                         rsurface.modelvertex3f_vertexbuffer = NULL;
8758                         rsurface.modelvertex3f_bufferoffset = 0;
8759                         rsurface.modelvertex3f_vertexbuffer = 0;
8760                         rsurface.modelvertex3f_bufferoffset = 0;
8761                         rsurface.modelsvector3f_vertexbuffer = 0;
8762                         rsurface.modelsvector3f_bufferoffset = 0;
8763                         rsurface.modeltvector3f_vertexbuffer = 0;
8764                         rsurface.modeltvector3f_bufferoffset = 0;
8765                         rsurface.modelnormal3f_vertexbuffer = 0;
8766                         rsurface.modelnormal3f_bufferoffset = 0;
8767                 }
8768                 else if (wantnormals)
8769                 {
8770                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8771                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8772                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8773                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8774                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8775                         rsurface.modelsvector3f = NULL;
8776                         rsurface.modeltvector3f = NULL;
8777                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8778                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8779                         rsurface.modelvertexmesh = NULL;
8780                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8781                         rsurface.modelvertexmesh_bufferoffset = 0;
8782                         rsurface.modelvertex3f_vertexbuffer = NULL;
8783                         rsurface.modelvertex3f_bufferoffset = 0;
8784                         rsurface.modelvertex3f_vertexbuffer = 0;
8785                         rsurface.modelvertex3f_bufferoffset = 0;
8786                         rsurface.modelsvector3f_vertexbuffer = 0;
8787                         rsurface.modelsvector3f_bufferoffset = 0;
8788                         rsurface.modeltvector3f_vertexbuffer = 0;
8789                         rsurface.modeltvector3f_bufferoffset = 0;
8790                         rsurface.modelnormal3f_vertexbuffer = 0;
8791                         rsurface.modelnormal3f_bufferoffset = 0;
8792                 }
8793                 else
8794                 {
8795                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8796                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8797                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8798                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8799                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8800                         rsurface.modelsvector3f = NULL;
8801                         rsurface.modeltvector3f = NULL;
8802                         rsurface.modelnormal3f = NULL;
8803                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8804                         rsurface.modelvertexmesh = NULL;
8805                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8806                         rsurface.modelvertexmesh_bufferoffset = 0;
8807                         rsurface.modelvertex3f_vertexbuffer = NULL;
8808                         rsurface.modelvertex3f_bufferoffset = 0;
8809                         rsurface.modelvertex3f_vertexbuffer = 0;
8810                         rsurface.modelvertex3f_bufferoffset = 0;
8811                         rsurface.modelsvector3f_vertexbuffer = 0;
8812                         rsurface.modelsvector3f_bufferoffset = 0;
8813                         rsurface.modeltvector3f_vertexbuffer = 0;
8814                         rsurface.modeltvector3f_bufferoffset = 0;
8815                         rsurface.modelnormal3f_vertexbuffer = 0;
8816                         rsurface.modelnormal3f_bufferoffset = 0;
8817                 }
8818                 rsurface.modelgeneratedvertex = true;
8819         }
8820         else
8821         {
8822                 if (rsurface.entityskeletaltransform3x4)
8823                 {
8824                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8825                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8826                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8827                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8828                 }
8829                 else
8830                 {
8831                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8832                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8833                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8834                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8835                 }
8836                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8837                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8838                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8839                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8840                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8841                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8842                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8843                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8844                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8845                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8846                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8847                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8848                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8849                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8850                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8851                 rsurface.modelgeneratedvertex = false;
8852         }
8853         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8854         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8855         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8856         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8857         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8858         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8859         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8860         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8861         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8862         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8863         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8864         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8865         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8866         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8867         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8868         rsurface.modelelement3i = model->surfmesh.data_element3i;
8869         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8870         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8871         rsurface.modelelement3s = model->surfmesh.data_element3s;
8872         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8873         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8874         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8875         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8876         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8877         rsurface.modelsurfaces = model->data_surfaces;
8878         rsurface.batchgeneratedvertex = false;
8879         rsurface.batchfirstvertex = 0;
8880         rsurface.batchnumvertices = 0;
8881         rsurface.batchfirsttriangle = 0;
8882         rsurface.batchnumtriangles = 0;
8883         rsurface.batchvertex3f  = NULL;
8884         rsurface.batchvertex3f_vertexbuffer = NULL;
8885         rsurface.batchvertex3f_bufferoffset = 0;
8886         rsurface.batchsvector3f = NULL;
8887         rsurface.batchsvector3f_vertexbuffer = NULL;
8888         rsurface.batchsvector3f_bufferoffset = 0;
8889         rsurface.batchtvector3f = NULL;
8890         rsurface.batchtvector3f_vertexbuffer = NULL;
8891         rsurface.batchtvector3f_bufferoffset = 0;
8892         rsurface.batchnormal3f  = NULL;
8893         rsurface.batchnormal3f_vertexbuffer = NULL;
8894         rsurface.batchnormal3f_bufferoffset = 0;
8895         rsurface.batchlightmapcolor4f = NULL;
8896         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8897         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8898         rsurface.batchtexcoordtexture2f = NULL;
8899         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8900         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8901         rsurface.batchtexcoordlightmap2f = NULL;
8902         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8903         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8904         rsurface.batchskeletalindex4ub = NULL;
8905         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8906         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8907         rsurface.batchskeletalweight4ub = NULL;
8908         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8909         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8910         rsurface.batchvertexmesh = NULL;
8911         rsurface.batchvertexmesh_vertexbuffer = NULL;
8912         rsurface.batchvertexmesh_bufferoffset = 0;
8913         rsurface.batchelement3i = NULL;
8914         rsurface.batchelement3i_indexbuffer = NULL;
8915         rsurface.batchelement3i_bufferoffset = 0;
8916         rsurface.batchelement3s = NULL;
8917         rsurface.batchelement3s_indexbuffer = NULL;
8918         rsurface.batchelement3s_bufferoffset = 0;
8919         rsurface.passcolor4f = NULL;
8920         rsurface.passcolor4f_vertexbuffer = NULL;
8921         rsurface.passcolor4f_bufferoffset = 0;
8922         rsurface.forcecurrenttextureupdate = false;
8923 }
8924
8925 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)
8926 {
8927         rsurface.entity = r_refdef.scene.worldentity;
8928         rsurface.skeleton = NULL;
8929         rsurface.ent_skinnum = 0;
8930         rsurface.ent_qwskin = -1;
8931         rsurface.ent_flags = entflags;
8932         rsurface.shadertime = r_refdef.scene.time - shadertime;
8933         rsurface.modelnumvertices = numvertices;
8934         rsurface.modelnumtriangles = numtriangles;
8935         rsurface.matrix = *matrix;
8936         rsurface.inversematrix = *inversematrix;
8937         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8938         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8939         R_EntityMatrix(&rsurface.matrix);
8940         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8941         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8942         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8943         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8944         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8945         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8946         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8947         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8948         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8949         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8950         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8951         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8952         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);
8953         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8954         rsurface.frameblend[0].lerp = 1;
8955         rsurface.ent_alttextures = false;
8956         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8957         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8958         rsurface.entityskeletaltransform3x4 = NULL;
8959         rsurface.entityskeletaltransform3x4buffer = NULL;
8960         rsurface.entityskeletaltransform3x4offset = 0;
8961         rsurface.entityskeletaltransform3x4size = 0;
8962         rsurface.entityskeletalnumtransforms = 0;
8963         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8964         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8965         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8966         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8967         if (wanttangents)
8968         {
8969                 rsurface.modelvertex3f = (float *)vertex3f;
8970                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8971                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8972                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8973         }
8974         else if (wantnormals)
8975         {
8976                 rsurface.modelvertex3f = (float *)vertex3f;
8977                 rsurface.modelsvector3f = NULL;
8978                 rsurface.modeltvector3f = NULL;
8979                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8980         }
8981         else
8982         {
8983                 rsurface.modelvertex3f = (float *)vertex3f;
8984                 rsurface.modelsvector3f = NULL;
8985                 rsurface.modeltvector3f = NULL;
8986                 rsurface.modelnormal3f = NULL;
8987         }
8988         rsurface.modelvertexmesh = NULL;
8989         rsurface.modelvertexmesh_vertexbuffer = NULL;
8990         rsurface.modelvertexmesh_bufferoffset = 0;
8991         rsurface.modelvertex3f_vertexbuffer = 0;
8992         rsurface.modelvertex3f_bufferoffset = 0;
8993         rsurface.modelsvector3f_vertexbuffer = 0;
8994         rsurface.modelsvector3f_bufferoffset = 0;
8995         rsurface.modeltvector3f_vertexbuffer = 0;
8996         rsurface.modeltvector3f_bufferoffset = 0;
8997         rsurface.modelnormal3f_vertexbuffer = 0;
8998         rsurface.modelnormal3f_bufferoffset = 0;
8999         rsurface.modelgeneratedvertex = true;
9000         rsurface.modellightmapcolor4f  = (float *)color4f;
9001         rsurface.modellightmapcolor4f_vertexbuffer = 0;
9002         rsurface.modellightmapcolor4f_bufferoffset = 0;
9003         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
9004         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9005         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9006         rsurface.modeltexcoordlightmap2f  = NULL;
9007         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9008         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9009         rsurface.modelskeletalindex4ub = NULL;
9010         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
9011         rsurface.modelskeletalindex4ub_bufferoffset = 0;
9012         rsurface.modelskeletalweight4ub = NULL;
9013         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
9014         rsurface.modelskeletalweight4ub_bufferoffset = 0;
9015         rsurface.modelelement3i = (int *)element3i;
9016         rsurface.modelelement3i_indexbuffer = NULL;
9017         rsurface.modelelement3i_bufferoffset = 0;
9018         rsurface.modelelement3s = (unsigned short *)element3s;
9019         rsurface.modelelement3s_indexbuffer = NULL;
9020         rsurface.modelelement3s_bufferoffset = 0;
9021         rsurface.modellightmapoffsets = NULL;
9022         rsurface.modelsurfaces = NULL;
9023         rsurface.batchgeneratedvertex = false;
9024         rsurface.batchfirstvertex = 0;
9025         rsurface.batchnumvertices = 0;
9026         rsurface.batchfirsttriangle = 0;
9027         rsurface.batchnumtriangles = 0;
9028         rsurface.batchvertex3f  = NULL;
9029         rsurface.batchvertex3f_vertexbuffer = NULL;
9030         rsurface.batchvertex3f_bufferoffset = 0;
9031         rsurface.batchsvector3f = NULL;
9032         rsurface.batchsvector3f_vertexbuffer = NULL;
9033         rsurface.batchsvector3f_bufferoffset = 0;
9034         rsurface.batchtvector3f = NULL;
9035         rsurface.batchtvector3f_vertexbuffer = NULL;
9036         rsurface.batchtvector3f_bufferoffset = 0;
9037         rsurface.batchnormal3f  = NULL;
9038         rsurface.batchnormal3f_vertexbuffer = NULL;
9039         rsurface.batchnormal3f_bufferoffset = 0;
9040         rsurface.batchlightmapcolor4f = NULL;
9041         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9042         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9043         rsurface.batchtexcoordtexture2f = NULL;
9044         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9045         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9046         rsurface.batchtexcoordlightmap2f = NULL;
9047         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9048         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9049         rsurface.batchskeletalindex4ub = NULL;
9050         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9051         rsurface.batchskeletalindex4ub_bufferoffset = 0;
9052         rsurface.batchskeletalweight4ub = NULL;
9053         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9054         rsurface.batchskeletalweight4ub_bufferoffset = 0;
9055         rsurface.batchvertexmesh = NULL;
9056         rsurface.batchvertexmesh_vertexbuffer = NULL;
9057         rsurface.batchvertexmesh_bufferoffset = 0;
9058         rsurface.batchelement3i = NULL;
9059         rsurface.batchelement3i_indexbuffer = NULL;
9060         rsurface.batchelement3i_bufferoffset = 0;
9061         rsurface.batchelement3s = NULL;
9062         rsurface.batchelement3s_indexbuffer = NULL;
9063         rsurface.batchelement3s_bufferoffset = 0;
9064         rsurface.passcolor4f = NULL;
9065         rsurface.passcolor4f_vertexbuffer = NULL;
9066         rsurface.passcolor4f_bufferoffset = 0;
9067         rsurface.forcecurrenttextureupdate = true;
9068
9069         if (rsurface.modelnumvertices && rsurface.modelelement3i)
9070         {
9071                 if ((wantnormals || wanttangents) && !normal3f)
9072                 {
9073                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9074                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9075                 }
9076                 if (wanttangents && !svector3f)
9077                 {
9078                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9079                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9080                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9081                 }
9082         }
9083 }
9084
9085 float RSurf_FogPoint(const float *v)
9086 {
9087         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9088         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9089         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9090         float FogHeightFade = r_refdef.fogheightfade;
9091         float fogfrac;
9092         unsigned int fogmasktableindex;
9093         if (r_refdef.fogplaneviewabove)
9094                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9095         else
9096                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9097         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9098         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9099 }
9100
9101 float RSurf_FogVertex(const float *v)
9102 {
9103         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9104         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9105         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9106         float FogHeightFade = rsurface.fogheightfade;
9107         float fogfrac;
9108         unsigned int fogmasktableindex;
9109         if (r_refdef.fogplaneviewabove)
9110                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9111         else
9112                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9113         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9114         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9115 }
9116
9117 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9118 {
9119         int i;
9120         for (i = 0;i < numelements;i++)
9121                 outelement3i[i] = inelement3i[i] + adjust;
9122 }
9123
9124 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9125 extern cvar_t gl_vbo;
9126 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9127 {
9128         int deformindex;
9129         int firsttriangle;
9130         int numtriangles;
9131         int firstvertex;
9132         int endvertex;
9133         int numvertices;
9134         int surfacefirsttriangle;
9135         int surfacenumtriangles;
9136         int surfacefirstvertex;
9137         int surfaceendvertex;
9138         int surfacenumvertices;
9139         int batchnumsurfaces = texturenumsurfaces;
9140         int batchnumvertices;
9141         int batchnumtriangles;
9142         int needsupdate;
9143         int i, j;
9144         qboolean gaps;
9145         qboolean dynamicvertex;
9146         float amplitude;
9147         float animpos;
9148         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9149         float waveparms[4];
9150         unsigned char *ub;
9151         q3shaderinfo_deform_t *deform;
9152         const msurface_t *surface, *firstsurface;
9153         r_vertexmesh_t *vertexmesh;
9154         if (!texturenumsurfaces)
9155                 return;
9156         // find vertex range of this surface batch
9157         gaps = false;
9158         firstsurface = texturesurfacelist[0];
9159         firsttriangle = firstsurface->num_firsttriangle;
9160         batchnumvertices = 0;
9161         batchnumtriangles = 0;
9162         firstvertex = endvertex = firstsurface->num_firstvertex;
9163         for (i = 0;i < texturenumsurfaces;i++)
9164         {
9165                 surface = texturesurfacelist[i];
9166                 if (surface != firstsurface + i)
9167                         gaps = true;
9168                 surfacefirstvertex = surface->num_firstvertex;
9169                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9170                 surfacenumvertices = surface->num_vertices;
9171                 surfacenumtriangles = surface->num_triangles;
9172                 if (firstvertex > surfacefirstvertex)
9173                         firstvertex = surfacefirstvertex;
9174                 if (endvertex < surfaceendvertex)
9175                         endvertex = surfaceendvertex;
9176                 batchnumvertices += surfacenumvertices;
9177                 batchnumtriangles += surfacenumtriangles;
9178         }
9179
9180         r_refdef.stats[r_stat_batch_batches]++;
9181         if (gaps)
9182                 r_refdef.stats[r_stat_batch_withgaps]++;
9183         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9184         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9185         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9186
9187         // we now know the vertex range used, and if there are any gaps in it
9188         rsurface.batchfirstvertex = firstvertex;
9189         rsurface.batchnumvertices = endvertex - firstvertex;
9190         rsurface.batchfirsttriangle = firsttriangle;
9191         rsurface.batchnumtriangles = batchnumtriangles;
9192
9193         // this variable holds flags for which properties have been updated that
9194         // may require regenerating vertexmesh array...
9195         needsupdate = 0;
9196
9197         // check if any dynamic vertex processing must occur
9198         dynamicvertex = false;
9199
9200         // a cvar to force the dynamic vertex path to be taken, for debugging
9201         if (r_batch_debugdynamicvertexpath.integer)
9202         {
9203                 if (!dynamicvertex)
9204                 {
9205                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9206                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9207                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9208                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9209                 }
9210                 dynamicvertex = true;
9211         }
9212
9213         // if there is a chance of animated vertex colors, it's a dynamic batch
9214         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9215         {
9216                 if (!dynamicvertex)
9217                 {
9218                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9219                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9220                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9221                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9222                 }
9223                 dynamicvertex = true;
9224                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9225         }
9226
9227         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9228         {
9229                 switch (deform->deform)
9230                 {
9231                 default:
9232                 case Q3DEFORM_PROJECTIONSHADOW:
9233                 case Q3DEFORM_TEXT0:
9234                 case Q3DEFORM_TEXT1:
9235                 case Q3DEFORM_TEXT2:
9236                 case Q3DEFORM_TEXT3:
9237                 case Q3DEFORM_TEXT4:
9238                 case Q3DEFORM_TEXT5:
9239                 case Q3DEFORM_TEXT6:
9240                 case Q3DEFORM_TEXT7:
9241                 case Q3DEFORM_NONE:
9242                         break;
9243                 case Q3DEFORM_AUTOSPRITE:
9244                         if (!dynamicvertex)
9245                         {
9246                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9247                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9248                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9249                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9250                         }
9251                         dynamicvertex = true;
9252                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9253                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9254                         break;
9255                 case Q3DEFORM_AUTOSPRITE2:
9256                         if (!dynamicvertex)
9257                         {
9258                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9259                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9260                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9261                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9262                         }
9263                         dynamicvertex = true;
9264                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9265                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9266                         break;
9267                 case Q3DEFORM_NORMAL:
9268                         if (!dynamicvertex)
9269                         {
9270                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9271                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9272                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9273                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9274                         }
9275                         dynamicvertex = true;
9276                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9277                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9278                         break;
9279                 case Q3DEFORM_WAVE:
9280                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9281                                 break; // if wavefunc is a nop, ignore this transform
9282                         if (!dynamicvertex)
9283                         {
9284                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9285                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9286                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9287                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9288                         }
9289                         dynamicvertex = true;
9290                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9291                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9292                         break;
9293                 case Q3DEFORM_BULGE:
9294                         if (!dynamicvertex)
9295                         {
9296                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9297                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9298                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9299                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9300                         }
9301                         dynamicvertex = true;
9302                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9303                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9304                         break;
9305                 case Q3DEFORM_MOVE:
9306                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9307                                 break; // if wavefunc is a nop, ignore this transform
9308                         if (!dynamicvertex)
9309                         {
9310                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9311                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9312                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9313                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9314                         }
9315                         dynamicvertex = true;
9316                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9317                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9318                         break;
9319                 }
9320         }
9321         if (rsurface.texture->materialshaderpass)
9322         {
9323                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9324                 {
9325                 default:
9326                 case Q3TCGEN_TEXTURE:
9327                         break;
9328                 case Q3TCGEN_LIGHTMAP:
9329                         if (!dynamicvertex)
9330                         {
9331                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9332                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9333                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9334                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9335                         }
9336                         dynamicvertex = true;
9337                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9338                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9339                         break;
9340                 case Q3TCGEN_VECTOR:
9341                         if (!dynamicvertex)
9342                         {
9343                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9344                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9345                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9346                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9347                         }
9348                         dynamicvertex = true;
9349                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9350                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9351                         break;
9352                 case Q3TCGEN_ENVIRONMENT:
9353                         if (!dynamicvertex)
9354                         {
9355                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9356                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9357                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9358                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9359                         }
9360                         dynamicvertex = true;
9361                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9362                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9363                         break;
9364                 }
9365                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9366                 {
9367                         if (!dynamicvertex)
9368                         {
9369                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9370                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9371                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9372                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9373                         }
9374                         dynamicvertex = true;
9375                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9376                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9377                 }
9378         }
9379
9380         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9381         {
9382                 if (!dynamicvertex)
9383                 {
9384                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9385                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9386                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9387                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9388                 }
9389                 dynamicvertex = true;
9390                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9391         }
9392
9393         // when the model data has no vertex buffer (dynamic mesh), we need to
9394         // eliminate gaps
9395         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9396                 batchneed |= BATCHNEED_NOGAPS;
9397
9398         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9399         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9400         // we ensure this by treating the vertex batch as dynamic...
9401         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9402         {
9403                 if (!dynamicvertex)
9404                 {
9405                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9406                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9407                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9408                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9409                 }
9410                 dynamicvertex = true;
9411         }
9412
9413         if (dynamicvertex)
9414         {
9415                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9416                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9417                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9418                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9419                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9420                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9421                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9422                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9423         }
9424
9425         // if needsupdate, we have to do a dynamic vertex batch for sure
9426         if (needsupdate & batchneed)
9427         {
9428                 if (!dynamicvertex)
9429                 {
9430                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9431                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9432                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9433                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9434                 }
9435                 dynamicvertex = true;
9436         }
9437
9438         // see if we need to build vertexmesh from arrays
9439         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9440         {
9441                 if (!dynamicvertex)
9442                 {
9443                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9444                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9445                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9446                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9447                 }
9448                 dynamicvertex = true;
9449         }
9450
9451         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9452         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9453                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9454
9455         rsurface.batchvertex3f = rsurface.modelvertex3f;
9456         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9457         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9458         rsurface.batchsvector3f = rsurface.modelsvector3f;
9459         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9460         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9461         rsurface.batchtvector3f = rsurface.modeltvector3f;
9462         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9463         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9464         rsurface.batchnormal3f = rsurface.modelnormal3f;
9465         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9466         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9467         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9468         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9469         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9470         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9471         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9472         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9473         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9474         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9475         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9476         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9477         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9478         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9479         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9480         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9481         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9482         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9483         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9484         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9485         rsurface.batchelement3i = rsurface.modelelement3i;
9486         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9487         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9488         rsurface.batchelement3s = rsurface.modelelement3s;
9489         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9490         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9491         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9492         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9493         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9494         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9495         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9496
9497         // if any dynamic vertex processing has to occur in software, we copy the
9498         // entire surface list together before processing to rebase the vertices
9499         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9500         //
9501         // if any gaps exist and we do not have a static vertex buffer, we have to
9502         // copy the surface list together to avoid wasting upload bandwidth on the
9503         // vertices in the gaps.
9504         //
9505         // if gaps exist and we have a static vertex buffer, we can choose whether
9506         // to combine the index buffer ranges into one dynamic index buffer or
9507         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9508         //
9509         // in many cases the batch is reduced to one draw call.
9510
9511         rsurface.batchmultidraw = false;
9512         rsurface.batchmultidrawnumsurfaces = 0;
9513         rsurface.batchmultidrawsurfacelist = NULL;
9514
9515         if (!dynamicvertex)
9516         {
9517                 // static vertex data, just set pointers...
9518                 rsurface.batchgeneratedvertex = false;
9519                 // if there are gaps, we want to build a combined index buffer,
9520                 // otherwise use the original static buffer with an appropriate offset
9521                 if (gaps)
9522                 {
9523                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9524                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9525                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9526                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9527                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9528                         {
9529                                 rsurface.batchmultidraw = true;
9530                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9531                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9532                                 return;
9533                         }
9534                         // build a new triangle elements array for this batch
9535                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9536                         rsurface.batchfirsttriangle = 0;
9537                         numtriangles = 0;
9538                         for (i = 0;i < texturenumsurfaces;i++)
9539                         {
9540                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9541                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9542                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9543                                 numtriangles += surfacenumtriangles;
9544                         }
9545                         rsurface.batchelement3i_indexbuffer = NULL;
9546                         rsurface.batchelement3i_bufferoffset = 0;
9547                         rsurface.batchelement3s = NULL;
9548                         rsurface.batchelement3s_indexbuffer = NULL;
9549                         rsurface.batchelement3s_bufferoffset = 0;
9550                         if (endvertex <= 65536)
9551                         {
9552                                 // make a 16bit (unsigned short) index array if possible
9553                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9554                                 for (i = 0;i < numtriangles*3;i++)
9555                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9556                         }
9557                         // upload buffer data for the copytriangles batch
9558                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9559                         {
9560                                 if (rsurface.batchelement3s)
9561                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9562                                 else if (rsurface.batchelement3i)
9563                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9564                         }
9565                 }
9566                 else
9567                 {
9568                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9569                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9570                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9571                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9572                 }
9573                 return;
9574         }
9575
9576         // something needs software processing, do it for real...
9577         // we only directly handle separate array data in this case and then
9578         // generate interleaved data if needed...
9579         rsurface.batchgeneratedvertex = true;
9580         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9581         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9582         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9583         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9584
9585         // now copy the vertex data into a combined array and make an index array
9586         // (this is what Quake3 does all the time)
9587         // we also apply any skeletal animation here that would have been done in
9588         // the vertex shader, because most of the dynamic vertex animation cases
9589         // need actual vertex positions and normals
9590         //if (dynamicvertex)
9591         {
9592                 rsurface.batchvertexmesh = NULL;
9593                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9594                 rsurface.batchvertexmesh_bufferoffset = 0;
9595                 rsurface.batchvertex3f = NULL;
9596                 rsurface.batchvertex3f_vertexbuffer = NULL;
9597                 rsurface.batchvertex3f_bufferoffset = 0;
9598                 rsurface.batchsvector3f = NULL;
9599                 rsurface.batchsvector3f_vertexbuffer = NULL;
9600                 rsurface.batchsvector3f_bufferoffset = 0;
9601                 rsurface.batchtvector3f = NULL;
9602                 rsurface.batchtvector3f_vertexbuffer = NULL;
9603                 rsurface.batchtvector3f_bufferoffset = 0;
9604                 rsurface.batchnormal3f = NULL;
9605                 rsurface.batchnormal3f_vertexbuffer = NULL;
9606                 rsurface.batchnormal3f_bufferoffset = 0;
9607                 rsurface.batchlightmapcolor4f = NULL;
9608                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9609                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9610                 rsurface.batchtexcoordtexture2f = NULL;
9611                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9612                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9613                 rsurface.batchtexcoordlightmap2f = NULL;
9614                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9615                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9616                 rsurface.batchskeletalindex4ub = NULL;
9617                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9618                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9619                 rsurface.batchskeletalweight4ub = NULL;
9620                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9621                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9622                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9623                 rsurface.batchelement3i_indexbuffer = NULL;
9624                 rsurface.batchelement3i_bufferoffset = 0;
9625                 rsurface.batchelement3s = NULL;
9626                 rsurface.batchelement3s_indexbuffer = NULL;
9627                 rsurface.batchelement3s_bufferoffset = 0;
9628                 rsurface.batchskeletaltransform3x4buffer = NULL;
9629                 rsurface.batchskeletaltransform3x4offset = 0;
9630                 rsurface.batchskeletaltransform3x4size = 0;
9631                 // we'll only be setting up certain arrays as needed
9632                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9633                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9634                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9635                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9636                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9637                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9638                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9639                 {
9640                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9641                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9642                 }
9643                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9644                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9645                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9646                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9647                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9648                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9649                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9650                 {
9651                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9652                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9653                 }
9654                 numvertices = 0;
9655                 numtriangles = 0;
9656                 for (i = 0;i < texturenumsurfaces;i++)
9657                 {
9658                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9659                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9660                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9661                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9662                         // copy only the data requested
9663                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9664                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9665                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9666                         {
9667                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9668                                 {
9669                                         if (rsurface.batchvertex3f)
9670                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9671                                         else
9672                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9673                                 }
9674                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9675                                 {
9676                                         if (rsurface.modelnormal3f)
9677                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9678                                         else
9679                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9680                                 }
9681                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9682                                 {
9683                                         if (rsurface.modelsvector3f)
9684                                         {
9685                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9686                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9687                                         }
9688                                         else
9689                                         {
9690                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9691                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9692                                         }
9693                                 }
9694                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9695                                 {
9696                                         if (rsurface.modellightmapcolor4f)
9697                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9698                                         else
9699                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9700                                 }
9701                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9702                                 {
9703                                         if (rsurface.modeltexcoordtexture2f)
9704                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9705                                         else
9706                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9707                                 }
9708                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9709                                 {
9710                                         if (rsurface.modeltexcoordlightmap2f)
9711                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9712                                         else
9713                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9714                                 }
9715                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9716                                 {
9717                                         if (rsurface.modelskeletalindex4ub)
9718                                         {
9719                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9720                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9721                                         }
9722                                         else
9723                                         {
9724                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9725                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9726                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9727                                                 for (j = 0;j < surfacenumvertices;j++)
9728                                                         ub[j*4] = 255;
9729                                         }
9730                                 }
9731                         }
9732                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9733                         numvertices += surfacenumvertices;
9734                         numtriangles += surfacenumtriangles;
9735                 }
9736
9737                 // generate a 16bit index array as well if possible
9738                 // (in general, dynamic batches fit)
9739                 if (numvertices <= 65536)
9740                 {
9741                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9742                         for (i = 0;i < numtriangles*3;i++)
9743                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9744                 }
9745
9746                 // since we've copied everything, the batch now starts at 0
9747                 rsurface.batchfirstvertex = 0;
9748                 rsurface.batchnumvertices = batchnumvertices;
9749                 rsurface.batchfirsttriangle = 0;
9750                 rsurface.batchnumtriangles = batchnumtriangles;
9751         }
9752
9753         // apply skeletal animation that would have been done in the vertex shader
9754         if (rsurface.batchskeletaltransform3x4)
9755         {
9756                 const unsigned char *si;
9757                 const unsigned char *sw;
9758                 const float *t[4];
9759                 const float *b = rsurface.batchskeletaltransform3x4;
9760                 float *vp, *vs, *vt, *vn;
9761                 float w[4];
9762                 float m[3][4], n[3][4];
9763                 float tp[3], ts[3], tt[3], tn[3];
9764                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9765                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9766                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9767                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9768                 si = rsurface.batchskeletalindex4ub;
9769                 sw = rsurface.batchskeletalweight4ub;
9770                 vp = rsurface.batchvertex3f;
9771                 vs = rsurface.batchsvector3f;
9772                 vt = rsurface.batchtvector3f;
9773                 vn = rsurface.batchnormal3f;
9774                 memset(m[0], 0, sizeof(m));
9775                 memset(n[0], 0, sizeof(n));
9776                 for (i = 0;i < batchnumvertices;i++)
9777                 {
9778                         t[0] = b + si[0]*12;
9779                         if (sw[0] == 255)
9780                         {
9781                                 // common case - only one matrix
9782                                 m[0][0] = t[0][ 0];
9783                                 m[0][1] = t[0][ 1];
9784                                 m[0][2] = t[0][ 2];
9785                                 m[0][3] = t[0][ 3];
9786                                 m[1][0] = t[0][ 4];
9787                                 m[1][1] = t[0][ 5];
9788                                 m[1][2] = t[0][ 6];
9789                                 m[1][3] = t[0][ 7];
9790                                 m[2][0] = t[0][ 8];
9791                                 m[2][1] = t[0][ 9];
9792                                 m[2][2] = t[0][10];
9793                                 m[2][3] = t[0][11];
9794                         }
9795                         else if (sw[2] + sw[3])
9796                         {
9797                                 // blend 4 matrices
9798                                 t[1] = b + si[1]*12;
9799                                 t[2] = b + si[2]*12;
9800                                 t[3] = b + si[3]*12;
9801                                 w[0] = sw[0] * (1.0f / 255.0f);
9802                                 w[1] = sw[1] * (1.0f / 255.0f);
9803                                 w[2] = sw[2] * (1.0f / 255.0f);
9804                                 w[3] = sw[3] * (1.0f / 255.0f);
9805                                 // blend the matrices
9806                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9807                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9808                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9809                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9810                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9811                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9812                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9813                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9814                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9815                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9816                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9817                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9818                         }
9819                         else
9820                         {
9821                                 // blend 2 matrices
9822                                 t[1] = b + si[1]*12;
9823                                 w[0] = sw[0] * (1.0f / 255.0f);
9824                                 w[1] = sw[1] * (1.0f / 255.0f);
9825                                 // blend the matrices
9826                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9827                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9828                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9829                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9830                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9831                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9832                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9833                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9834                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9835                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9836                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9837                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9838                         }
9839                         si += 4;
9840                         sw += 4;
9841                         // modify the vertex
9842                         VectorCopy(vp, tp);
9843                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9844                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9845                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9846                         vp += 3;
9847                         if (vn)
9848                         {
9849                                 // the normal transformation matrix is a set of cross products...
9850                                 CrossProduct(m[1], m[2], n[0]);
9851                                 CrossProduct(m[2], m[0], n[1]);
9852                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9853                                 VectorCopy(vn, tn);
9854                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9855                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9856                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9857                                 VectorNormalize(vn);
9858                                 vn += 3;
9859                                 if (vs)
9860                                 {
9861                                         VectorCopy(vs, ts);
9862                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9863                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9864                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9865                                         VectorNormalize(vs);
9866                                         vs += 3;
9867                                         VectorCopy(vt, tt);
9868                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9869                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9870                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9871                                         VectorNormalize(vt);
9872                                         vt += 3;
9873                                 }
9874                         }
9875                 }
9876                 rsurface.batchskeletaltransform3x4 = NULL;
9877                 rsurface.batchskeletalnumtransforms = 0;
9878         }
9879
9880         // q1bsp surfaces rendered in vertex color mode have to have colors
9881         // calculated based on lightstyles
9882         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9883         {
9884                 // generate color arrays for the surfaces in this list
9885                 int c[4];
9886                 int scale;
9887                 int size3;
9888                 const int *offsets;
9889                 const unsigned char *lm;
9890                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9891                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9892                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9893                 numvertices = 0;
9894                 for (i = 0;i < texturenumsurfaces;i++)
9895                 {
9896                         surface = texturesurfacelist[i];
9897                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9898                         surfacenumvertices = surface->num_vertices;
9899                         if (surface->lightmapinfo->samples)
9900                         {
9901                                 for (j = 0;j < surfacenumvertices;j++)
9902                                 {
9903                                         lm = surface->lightmapinfo->samples + offsets[j];
9904                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9905                                         VectorScale(lm, scale, c);
9906                                         if (surface->lightmapinfo->styles[1] != 255)
9907                                         {
9908                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9909                                                 lm += size3;
9910                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9911                                                 VectorMA(c, scale, lm, c);
9912                                                 if (surface->lightmapinfo->styles[2] != 255)
9913                                                 {
9914                                                         lm += size3;
9915                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9916                                                         VectorMA(c, scale, lm, c);
9917                                                         if (surface->lightmapinfo->styles[3] != 255)
9918                                                         {
9919                                                                 lm += size3;
9920                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9921                                                                 VectorMA(c, scale, lm, c);
9922                                                         }
9923                                                 }
9924                                         }
9925                                         c[0] >>= 7;
9926                                         c[1] >>= 7;
9927                                         c[2] >>= 7;
9928                                         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);
9929                                         numvertices++;
9930                                 }
9931                         }
9932                         else
9933                         {
9934                                 for (j = 0;j < surfacenumvertices;j++)
9935                                 {
9936                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9937                                         numvertices++;
9938                                 }
9939                         }
9940                 }
9941         }
9942
9943         // if vertices are deformed (sprite flares and things in maps, possibly
9944         // water waves, bulges and other deformations), modify the copied vertices
9945         // in place
9946         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9947         {
9948                 float scale;
9949                 switch (deform->deform)
9950                 {
9951                 default:
9952                 case Q3DEFORM_PROJECTIONSHADOW:
9953                 case Q3DEFORM_TEXT0:
9954                 case Q3DEFORM_TEXT1:
9955                 case Q3DEFORM_TEXT2:
9956                 case Q3DEFORM_TEXT3:
9957                 case Q3DEFORM_TEXT4:
9958                 case Q3DEFORM_TEXT5:
9959                 case Q3DEFORM_TEXT6:
9960                 case Q3DEFORM_TEXT7:
9961                 case Q3DEFORM_NONE:
9962                         break;
9963                 case Q3DEFORM_AUTOSPRITE:
9964                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9965                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9966                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9967                         VectorNormalize(newforward);
9968                         VectorNormalize(newright);
9969                         VectorNormalize(newup);
9970 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9971 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9972 //                      rsurface.batchvertex3f_bufferoffset = 0;
9973 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9974 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9975 //                      rsurface.batchsvector3f_bufferoffset = 0;
9976 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9977 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9978 //                      rsurface.batchtvector3f_bufferoffset = 0;
9979 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9980 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9981 //                      rsurface.batchnormal3f_bufferoffset = 0;
9982                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9983                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9984                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9985                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9986                                 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);
9987                         // a single autosprite surface can contain multiple sprites...
9988                         for (j = 0;j < batchnumvertices - 3;j += 4)
9989                         {
9990                                 VectorClear(center);
9991                                 for (i = 0;i < 4;i++)
9992                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9993                                 VectorScale(center, 0.25f, center);
9994                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9995                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9996                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9997                                 for (i = 0;i < 4;i++)
9998                                 {
9999                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10000                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
10001                                 }
10002                         }
10003                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
10004                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10005                         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);
10006                         break;
10007                 case Q3DEFORM_AUTOSPRITE2:
10008                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10009                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10010                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10011                         VectorNormalize(newforward);
10012                         VectorNormalize(newright);
10013                         VectorNormalize(newup);
10014 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10015 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10016 //                      rsurface.batchvertex3f_bufferoffset = 0;
10017                         {
10018                                 const float *v1, *v2;
10019                                 vec3_t start, end;
10020                                 float f, l;
10021                                 struct
10022                                 {
10023                                         float length2;
10024                                         const float *v1;
10025                                         const float *v2;
10026                                 }
10027                                 shortest[2];
10028                                 memset(shortest, 0, sizeof(shortest));
10029                                 // a single autosprite surface can contain multiple sprites...
10030                                 for (j = 0;j < batchnumvertices - 3;j += 4)
10031                                 {
10032                                         VectorClear(center);
10033                                         for (i = 0;i < 4;i++)
10034                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10035                                         VectorScale(center, 0.25f, center);
10036                                         // find the two shortest edges, then use them to define the
10037                                         // axis vectors for rotating around the central axis
10038                                         for (i = 0;i < 6;i++)
10039                                         {
10040                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10041                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10042                                                 l = VectorDistance2(v1, v2);
10043                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10044                                                 if (v1[2] != v2[2])
10045                                                         l += (1.0f / 1024.0f);
10046                                                 if (shortest[0].length2 > l || i == 0)
10047                                                 {
10048                                                         shortest[1] = shortest[0];
10049                                                         shortest[0].length2 = l;
10050                                                         shortest[0].v1 = v1;
10051                                                         shortest[0].v2 = v2;
10052                                                 }
10053                                                 else if (shortest[1].length2 > l || i == 1)
10054                                                 {
10055                                                         shortest[1].length2 = l;
10056                                                         shortest[1].v1 = v1;
10057                                                         shortest[1].v2 = v2;
10058                                                 }
10059                                         }
10060                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10061                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10062                                         // this calculates the right vector from the shortest edge
10063                                         // and the up vector from the edge midpoints
10064                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10065                                         VectorNormalize(right);
10066                                         VectorSubtract(end, start, up);
10067                                         VectorNormalize(up);
10068                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10069                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10070                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10071                                         VectorNegate(forward, forward);
10072                                         VectorReflect(forward, 0, up, forward);
10073                                         VectorNormalize(forward);
10074                                         CrossProduct(up, forward, newright);
10075                                         VectorNormalize(newright);
10076                                         // rotate the quad around the up axis vector, this is made
10077                                         // especially easy by the fact we know the quad is flat,
10078                                         // so we only have to subtract the center position and
10079                                         // measure distance along the right vector, and then
10080                                         // multiply that by the newright vector and add back the
10081                                         // center position
10082                                         // we also need to subtract the old position to undo the
10083                                         // displacement from the center, which we do with a
10084                                         // DotProduct, the subtraction/addition of center is also
10085                                         // optimized into DotProducts here
10086                                         l = DotProduct(right, center);
10087                                         for (i = 0;i < 4;i++)
10088                                         {
10089                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10090                                                 f = DotProduct(right, v1) - l;
10091                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10092                                         }
10093                                 }
10094                         }
10095                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10096                         {
10097 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10098 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10099 //                              rsurface.batchnormal3f_bufferoffset = 0;
10100                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10101                         }
10102                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10103                         {
10104 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10105 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10106 //                              rsurface.batchsvector3f_bufferoffset = 0;
10107 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10108 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10109 //                              rsurface.batchtvector3f_bufferoffset = 0;
10110                                 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);
10111                         }
10112                         break;
10113                 case Q3DEFORM_NORMAL:
10114                         // deform the normals to make reflections wavey
10115                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10116                         rsurface.batchnormal3f_vertexbuffer = NULL;
10117                         rsurface.batchnormal3f_bufferoffset = 0;
10118                         for (j = 0;j < batchnumvertices;j++)
10119                         {
10120                                 float vertex[3];
10121                                 float *normal = rsurface.batchnormal3f + 3*j;
10122                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10123                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10124                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10125                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10126                                 VectorNormalize(normal);
10127                         }
10128                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10129                         {
10130 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10131 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10132 //                              rsurface.batchsvector3f_bufferoffset = 0;
10133 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10134 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10135 //                              rsurface.batchtvector3f_bufferoffset = 0;
10136                                 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);
10137                         }
10138                         break;
10139                 case Q3DEFORM_WAVE:
10140                         // deform vertex array to make wavey water and flags and such
10141                         waveparms[0] = deform->waveparms[0];
10142                         waveparms[1] = deform->waveparms[1];
10143                         waveparms[2] = deform->waveparms[2];
10144                         waveparms[3] = deform->waveparms[3];
10145                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10146                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10147                         // this is how a divisor of vertex influence on deformation
10148                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10149                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10150 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10151 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10152 //                      rsurface.batchvertex3f_bufferoffset = 0;
10153 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10154 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10155 //                      rsurface.batchnormal3f_bufferoffset = 0;
10156                         for (j = 0;j < batchnumvertices;j++)
10157                         {
10158                                 // if the wavefunc depends on time, evaluate it per-vertex
10159                                 if (waveparms[3])
10160                                 {
10161                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10162                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10163                                 }
10164                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10165                         }
10166                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10167                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10168                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10169                         {
10170 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10171 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10172 //                              rsurface.batchsvector3f_bufferoffset = 0;
10173 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10174 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10175 //                              rsurface.batchtvector3f_bufferoffset = 0;
10176                                 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);
10177                         }
10178                         break;
10179                 case Q3DEFORM_BULGE:
10180                         // deform vertex array to make the surface have moving bulges
10181 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10182 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10183 //                      rsurface.batchvertex3f_bufferoffset = 0;
10184 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10185 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10186 //                      rsurface.batchnormal3f_bufferoffset = 0;
10187                         for (j = 0;j < batchnumvertices;j++)
10188                         {
10189                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10190                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10191                         }
10192                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10193                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10194                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10195                         {
10196 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10197 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10198 //                              rsurface.batchsvector3f_bufferoffset = 0;
10199 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10200 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10201 //                              rsurface.batchtvector3f_bufferoffset = 0;
10202                                 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);
10203                         }
10204                         break;
10205                 case Q3DEFORM_MOVE:
10206                         // deform vertex array
10207                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10208                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10209                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10210                         VectorScale(deform->parms, scale, waveparms);
10211 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10212 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10213 //                      rsurface.batchvertex3f_bufferoffset = 0;
10214                         for (j = 0;j < batchnumvertices;j++)
10215                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10216                         break;
10217                 }
10218         }
10219
10220         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10221         {
10222         // generate texcoords based on the chosen texcoord source
10223                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10224                 {
10225                 default:
10226                 case Q3TCGEN_TEXTURE:
10227                         break;
10228                 case Q3TCGEN_LIGHTMAP:
10229         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10230         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10231         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10232                         if (rsurface.batchtexcoordlightmap2f)
10233                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10234                         break;
10235                 case Q3TCGEN_VECTOR:
10236         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10237         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10238         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10239                         for (j = 0;j < batchnumvertices;j++)
10240                         {
10241                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10242                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10243                         }
10244                         break;
10245                 case Q3TCGEN_ENVIRONMENT:
10246                         // make environment reflections using a spheremap
10247                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10248                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10249                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10250                         for (j = 0;j < batchnumvertices;j++)
10251                         {
10252                                 // identical to Q3A's method, but executed in worldspace so
10253                                 // carried models can be shiny too
10254
10255                                 float viewer[3], d, reflected[3], worldreflected[3];
10256
10257                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10258                                 // VectorNormalize(viewer);
10259
10260                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10261
10262                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10263                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10264                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10265                                 // note: this is proportinal to viewer, so we can normalize later
10266
10267                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10268                                 VectorNormalize(worldreflected);
10269
10270                                 // note: this sphere map only uses world x and z!
10271                                 // so positive and negative y will LOOK THE SAME.
10272                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10273                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10274                         }
10275                         break;
10276                 }
10277                 // the only tcmod that needs software vertex processing is turbulent, so
10278                 // check for it here and apply the changes if needed
10279                 // and we only support that as the first one
10280                 // (handling a mixture of turbulent and other tcmods would be problematic
10281                 //  without punting it entirely to a software path)
10282                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10283                 {
10284                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10285                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10286         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10287         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10288         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10289                         for (j = 0;j < batchnumvertices;j++)
10290                         {
10291                                 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);
10292                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10293                         }
10294                 }
10295         }
10296
10297         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10298         {
10299                 // convert the modified arrays to vertex structs
10300 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10301 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10302 //              rsurface.batchvertexmesh_bufferoffset = 0;
10303                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10304                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10305                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10306                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10307                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10308                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10309                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10310                 {
10311                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10312                         {
10313                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10314                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10315                         }
10316                 }
10317                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10318                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10319                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10320                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10321                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10322                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10323                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10324                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10325                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10326                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10327                 {
10328                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10329                         {
10330                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10331                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10332                         }
10333                 }
10334         }
10335
10336         // upload buffer data for the dynamic batch
10337         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10338         {
10339                 if (rsurface.batchvertexmesh)
10340                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10341                 else
10342                 {
10343                         if (rsurface.batchvertex3f)
10344                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10345                         if (rsurface.batchsvector3f)
10346                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10347                         if (rsurface.batchtvector3f)
10348                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10349                         if (rsurface.batchnormal3f)
10350                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10351                         if (rsurface.batchlightmapcolor4f)
10352                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10353                         if (rsurface.batchtexcoordtexture2f)
10354                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10355                         if (rsurface.batchtexcoordlightmap2f)
10356                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10357                         if (rsurface.batchskeletalindex4ub)
10358                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10359                         if (rsurface.batchskeletalweight4ub)
10360                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10361                 }
10362                 if (rsurface.batchelement3s)
10363                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10364                 else if (rsurface.batchelement3i)
10365                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10366         }
10367 }
10368
10369 void RSurf_DrawBatch(void)
10370 {
10371         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10372         // through the pipeline, killing it earlier in the pipeline would have
10373         // per-surface overhead rather than per-batch overhead, so it's best to
10374         // reject it here, before it hits glDraw.
10375         if (rsurface.batchnumtriangles == 0)
10376                 return;
10377 #if 0
10378         // batch debugging code
10379         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10380         {
10381                 int i;
10382                 int j;
10383                 int c;
10384                 const int *e;
10385                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10386                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10387                 {
10388                         c = e[i];
10389                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10390                         {
10391                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10392                                 {
10393                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10394                                                 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);
10395                                         break;
10396                                 }
10397                         }
10398                 }
10399         }
10400 #endif
10401         if (rsurface.batchmultidraw)
10402         {
10403                 // issue multiple draws rather than copying index data
10404                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10405                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10406                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10407                 for (i = 0;i < numsurfaces;)
10408                 {
10409                         // combine consecutive surfaces as one draw
10410                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10411                                 if (surfacelist[j] != surfacelist[k] + 1)
10412                                         break;
10413                         firstvertex = surfacelist[i]->num_firstvertex;
10414                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10415                         firsttriangle = surfacelist[i]->num_firsttriangle;
10416                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10417                         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);
10418                         i = j;
10419                 }
10420         }
10421         else
10422         {
10423                 // there is only one consecutive run of index data (may have been combined)
10424                 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);
10425         }
10426 }
10427
10428 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10429 {
10430         // pick the closest matching water plane
10431         int planeindex, vertexindex, bestplaneindex = -1;
10432         float d, bestd;
10433         vec3_t vert;
10434         const float *v;
10435         r_waterstate_waterplane_t *p;
10436         qboolean prepared = false;
10437         bestd = 0;
10438         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10439         {
10440                 if(p->camera_entity != rsurface.texture->camera_entity)
10441                         continue;
10442                 d = 0;
10443                 if(!prepared)
10444                 {
10445                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10446                         prepared = true;
10447                         if(rsurface.batchnumvertices == 0)
10448                                 break;
10449                 }
10450                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10451                 {
10452                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10453                         d += fabs(PlaneDiff(vert, &p->plane));
10454                 }
10455                 if (bestd > d || bestplaneindex < 0)
10456                 {
10457                         bestd = d;
10458                         bestplaneindex = planeindex;
10459                 }
10460         }
10461         return bestplaneindex;
10462         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10463         // this situation though, as it might be better to render single larger
10464         // batches with useless stuff (backface culled for example) than to
10465         // render multiple smaller batches
10466 }
10467
10468 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10469 {
10470         int i;
10471         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10472         rsurface.passcolor4f_vertexbuffer = 0;
10473         rsurface.passcolor4f_bufferoffset = 0;
10474         for (i = 0;i < rsurface.batchnumvertices;i++)
10475                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10476 }
10477
10478 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10479 {
10480         int i;
10481         float f;
10482         const float *v;
10483         const float *c;
10484         float *c2;
10485         if (rsurface.passcolor4f)
10486         {
10487                 // generate color arrays
10488                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10489                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10490                 rsurface.passcolor4f_vertexbuffer = 0;
10491                 rsurface.passcolor4f_bufferoffset = 0;
10492                 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)
10493                 {
10494                         f = RSurf_FogVertex(v);
10495                         c2[0] = c[0] * f;
10496                         c2[1] = c[1] * f;
10497                         c2[2] = c[2] * f;
10498                         c2[3] = c[3];
10499                 }
10500         }
10501         else
10502         {
10503                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10504                 rsurface.passcolor4f_vertexbuffer = 0;
10505                 rsurface.passcolor4f_bufferoffset = 0;
10506                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10507                 {
10508                         f = RSurf_FogVertex(v);
10509                         c2[0] = f;
10510                         c2[1] = f;
10511                         c2[2] = f;
10512                         c2[3] = 1;
10513                 }
10514         }
10515 }
10516
10517 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10518 {
10519         int i;
10520         float f;
10521         const float *v;
10522         const float *c;
10523         float *c2;
10524         if (!rsurface.passcolor4f)
10525                 return;
10526         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10527         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10528         rsurface.passcolor4f_vertexbuffer = 0;
10529         rsurface.passcolor4f_bufferoffset = 0;
10530         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)
10531         {
10532                 f = RSurf_FogVertex(v);
10533                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10534                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10535                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10536                 c2[3] = c[3];
10537         }
10538 }
10539
10540 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10541 {
10542         int i;
10543         const float *c;
10544         float *c2;
10545         if (!rsurface.passcolor4f)
10546                 return;
10547         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10548         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10549         rsurface.passcolor4f_vertexbuffer = 0;
10550         rsurface.passcolor4f_bufferoffset = 0;
10551         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10552         {
10553                 c2[0] = c[0] * r;
10554                 c2[1] = c[1] * g;
10555                 c2[2] = c[2] * b;
10556                 c2[3] = c[3] * a;
10557         }
10558 }
10559
10560 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10561 {
10562         int i;
10563         const float *c;
10564         float *c2;
10565         if (!rsurface.passcolor4f)
10566                 return;
10567         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10568         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10569         rsurface.passcolor4f_vertexbuffer = 0;
10570         rsurface.passcolor4f_bufferoffset = 0;
10571         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10572         {
10573                 c2[0] = c[0] + r_refdef.scene.ambient;
10574                 c2[1] = c[1] + r_refdef.scene.ambient;
10575                 c2[2] = c[2] + r_refdef.scene.ambient;
10576                 c2[3] = c[3];
10577         }
10578 }
10579
10580 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10581 {
10582         // TODO: optimize
10583         rsurface.passcolor4f = NULL;
10584         rsurface.passcolor4f_vertexbuffer = 0;
10585         rsurface.passcolor4f_bufferoffset = 0;
10586         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10587         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10588         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10589         GL_Color(r, g, b, a);
10590         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10591         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10592         R_Mesh_TexMatrix(0, NULL);
10593         RSurf_DrawBatch();
10594 }
10595
10596 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10597 {
10598         // TODO: optimize applyfog && applycolor case
10599         // just apply fog if necessary, and tint the fog color array if necessary
10600         rsurface.passcolor4f = NULL;
10601         rsurface.passcolor4f_vertexbuffer = 0;
10602         rsurface.passcolor4f_bufferoffset = 0;
10603         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10604         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10605         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10606         GL_Color(r, g, b, a);
10607         RSurf_DrawBatch();
10608 }
10609
10610 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10611 {
10612         // TODO: optimize
10613         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10614         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10615         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10616         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10617         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10618         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10619         GL_Color(r, g, b, a);
10620         RSurf_DrawBatch();
10621 }
10622
10623 static void RSurf_DrawBatch_GL11_ClampColor(void)
10624 {
10625         int i;
10626         const float *c1;
10627         float *c2;
10628         if (!rsurface.passcolor4f)
10629                 return;
10630         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10631         {
10632                 c2[0] = bound(0.0f, c1[0], 1.0f);
10633                 c2[1] = bound(0.0f, c1[1], 1.0f);
10634                 c2[2] = bound(0.0f, c1[2], 1.0f);
10635                 c2[3] = bound(0.0f, c1[3], 1.0f);
10636         }
10637 }
10638
10639 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10640 {
10641         int i;
10642         float f;
10643         const float *v;
10644         const float *n;
10645         float *c;
10646         //vec3_t eyedir;
10647
10648         // fake shading
10649         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10650         rsurface.passcolor4f_vertexbuffer = 0;
10651         rsurface.passcolor4f_bufferoffset = 0;
10652         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)
10653         {
10654                 f = -DotProduct(r_refdef.view.forward, n);
10655                 f = max(0, f);
10656                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10657                 f *= r_refdef.lightmapintensity;
10658                 Vector4Set(c, f, f, f, 1);
10659         }
10660 }
10661
10662 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10663 {
10664         RSurf_DrawBatch_GL11_ApplyFakeLight();
10665         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10666         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10667         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10668         GL_Color(r, g, b, a);
10669         RSurf_DrawBatch();
10670 }
10671
10672 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10673 {
10674         int i;
10675         float f;
10676         float alpha;
10677         const float *v;
10678         const float *n;
10679         float *c;
10680         vec3_t ambientcolor;
10681         vec3_t diffusecolor;
10682         vec3_t lightdir;
10683         // TODO: optimize
10684         // model lighting
10685         VectorCopy(rsurface.modellight_lightdir, lightdir);
10686         f = 0.5f * r_refdef.lightmapintensity;
10687         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10688         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10689         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10690         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10691         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10692         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10693         alpha = *a;
10694         if (VectorLength2(diffusecolor) > 0)
10695         {
10696                 // q3-style directional shading
10697                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10698                 rsurface.passcolor4f_vertexbuffer = 0;
10699                 rsurface.passcolor4f_bufferoffset = 0;
10700                 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)
10701                 {
10702                         if ((f = DotProduct(n, lightdir)) > 0)
10703                                 VectorMA(ambientcolor, f, diffusecolor, c);
10704                         else
10705                                 VectorCopy(ambientcolor, c);
10706                         c[3] = alpha;
10707                 }
10708                 *r = 1;
10709                 *g = 1;
10710                 *b = 1;
10711                 *a = 1;
10712                 *applycolor = false;
10713         }
10714         else
10715         {
10716                 *r = ambientcolor[0];
10717                 *g = ambientcolor[1];
10718                 *b = ambientcolor[2];
10719                 rsurface.passcolor4f = NULL;
10720                 rsurface.passcolor4f_vertexbuffer = 0;
10721                 rsurface.passcolor4f_bufferoffset = 0;
10722         }
10723 }
10724
10725 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10726 {
10727         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10728         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10729         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10730         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10731         GL_Color(r, g, b, a);
10732         RSurf_DrawBatch();
10733 }
10734
10735 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10736 {
10737         int i;
10738         float f;
10739         const float *v;
10740         float *c;
10741
10742         // fake shading
10743         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10744         rsurface.passcolor4f_vertexbuffer = 0;
10745         rsurface.passcolor4f_bufferoffset = 0;
10746
10747         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10748         {
10749                 f = 1 - RSurf_FogVertex(v);
10750                 c[0] = r;
10751                 c[1] = g;
10752                 c[2] = b;
10753                 c[3] = f * a;
10754         }
10755 }
10756
10757 void RSurf_SetupDepthAndCulling(void)
10758 {
10759         // submodels are biased to avoid z-fighting with world surfaces that they
10760         // may be exactly overlapping (avoids z-fighting artifacts on certain
10761         // doors and things in Quake maps)
10762         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10763         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10764         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10765         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10766 }
10767
10768 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10769 {
10770         // transparent sky would be ridiculous
10771         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10772                 return;
10773         R_SetupShader_Generic_NoTexture(false, false);
10774         skyrenderlater = true;
10775         RSurf_SetupDepthAndCulling();
10776         GL_DepthMask(true);
10777         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10778         // skymasking on them, and Quake3 never did sky masking (unlike
10779         // software Quake and software Quake2), so disable the sky masking
10780         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10781         // and skymasking also looks very bad when noclipping outside the
10782         // level, so don't use it then either.
10783         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10784         {
10785                 R_Mesh_ResetTextureState();
10786                 if (skyrendermasked)
10787                 {
10788                         R_SetupShader_DepthOrShadow(false, false, false);
10789                         // depth-only (masking)
10790                         GL_ColorMask(0,0,0,0);
10791                         // just to make sure that braindead drivers don't draw
10792                         // anything despite that colormask...
10793                         GL_BlendFunc(GL_ZERO, GL_ONE);
10794                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10795                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10796                 }
10797                 else
10798                 {
10799                         R_SetupShader_Generic_NoTexture(false, false);
10800                         // fog sky
10801                         GL_BlendFunc(GL_ONE, GL_ZERO);
10802                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10803                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10804                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10805                 }
10806                 RSurf_DrawBatch();
10807                 if (skyrendermasked)
10808                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10809         }
10810         R_Mesh_ResetTextureState();
10811         GL_Color(1, 1, 1, 1);
10812 }
10813
10814 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10815 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10816 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10817 {
10818         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10819                 return;
10820         if (prepass)
10821         {
10822                 // render screenspace normalmap to texture
10823                 GL_DepthMask(true);
10824                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10825                 RSurf_DrawBatch();
10826                 return;
10827         }
10828
10829         // bind lightmap texture
10830
10831         // water/refraction/reflection/camera surfaces have to be handled specially
10832         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10833         {
10834                 int start, end, startplaneindex;
10835                 for (start = 0;start < texturenumsurfaces;start = end)
10836                 {
10837                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10838                         if(startplaneindex < 0)
10839                         {
10840                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10841                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10842                                 end = start + 1;
10843                                 continue;
10844                         }
10845                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10846                                 ;
10847                         // now that we have a batch using the same planeindex, render it
10848                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10849                         {
10850                                 // render water or distortion background
10851                                 GL_DepthMask(true);
10852                                 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);
10853                                 RSurf_DrawBatch();
10854                                 // blend surface on top
10855                                 GL_DepthMask(false);
10856                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10857                                 RSurf_DrawBatch();
10858                         }
10859                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10860                         {
10861                                 // render surface with reflection texture as input
10862                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10863                                 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);
10864                                 RSurf_DrawBatch();
10865                         }
10866                 }
10867                 return;
10868         }
10869
10870         // render surface batch normally
10871         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10872         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);
10873         RSurf_DrawBatch();
10874 }
10875
10876 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10877 {
10878         // OpenGL 1.3 path - anything not completely ancient
10879         qboolean applycolor;
10880         qboolean applyfog;
10881         int layerindex;
10882         const texturelayer_t *layer;
10883         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);
10884         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10885
10886         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10887         {
10888                 vec4_t layercolor;
10889                 int layertexrgbscale;
10890                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10891                 {
10892                         if (layerindex == 0)
10893                                 GL_AlphaTest(true);
10894                         else
10895                         {
10896                                 GL_AlphaTest(false);
10897                                 GL_DepthFunc(GL_EQUAL);
10898                         }
10899                 }
10900                 GL_DepthMask(layer->depthmask && writedepth);
10901                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10902                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10903                 {
10904                         layertexrgbscale = 4;
10905                         VectorScale(layer->color, 0.25f, layercolor);
10906                 }
10907                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10908                 {
10909                         layertexrgbscale = 2;
10910                         VectorScale(layer->color, 0.5f, layercolor);
10911                 }
10912                 else
10913                 {
10914                         layertexrgbscale = 1;
10915                         VectorScale(layer->color, 1.0f, layercolor);
10916                 }
10917                 layercolor[3] = layer->color[3];
10918                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10919                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10920                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10921                 switch (layer->type)
10922                 {
10923                 case TEXTURELAYERTYPE_LITTEXTURE:
10924                         // single-pass lightmapped texture with 2x rgbscale
10925                         R_Mesh_TexBind(0, r_texture_white);
10926                         R_Mesh_TexMatrix(0, NULL);
10927                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10928                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10929                         R_Mesh_TexBind(1, layer->texture);
10930                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10931                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10932                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10933                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10934                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10935                         else if (FAKELIGHT_ENABLED)
10936                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10937                         else if (rsurface.uselightmaptexture)
10938                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10939                         else
10940                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10941                         break;
10942                 case TEXTURELAYERTYPE_TEXTURE:
10943                         // singletexture unlit texture with transparency support
10944                         R_Mesh_TexBind(0, layer->texture);
10945                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10946                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10947                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10948                         R_Mesh_TexBind(1, 0);
10949                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10950                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10951                         break;
10952                 case TEXTURELAYERTYPE_FOG:
10953                         // singletexture fogging
10954                         if (layer->texture)
10955                         {
10956                                 R_Mesh_TexBind(0, layer->texture);
10957                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10958                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10959                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10960                         }
10961                         else
10962                         {
10963                                 R_Mesh_TexBind(0, 0);
10964                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10965                         }
10966                         R_Mesh_TexBind(1, 0);
10967                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10968                         // generate a color array for the fog pass
10969                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10970                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10971                         RSurf_DrawBatch();
10972                         break;
10973                 default:
10974                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10975                 }
10976         }
10977         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10978         {
10979                 GL_DepthFunc(GL_LEQUAL);
10980                 GL_AlphaTest(false);
10981         }
10982 }
10983
10984 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10985 {
10986         // OpenGL 1.1 - crusty old voodoo path
10987         qboolean applyfog;
10988         int layerindex;
10989         const texturelayer_t *layer;
10990         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);
10991         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10992
10993         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10994         {
10995                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10996                 {
10997                         if (layerindex == 0)
10998                                 GL_AlphaTest(true);
10999                         else
11000                         {
11001                                 GL_AlphaTest(false);
11002                                 GL_DepthFunc(GL_EQUAL);
11003                         }
11004                 }
11005                 GL_DepthMask(layer->depthmask && writedepth);
11006                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11007                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11008                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11009                 switch (layer->type)
11010                 {
11011                 case TEXTURELAYERTYPE_LITTEXTURE:
11012                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
11013                         {
11014                                 // two-pass lit texture with 2x rgbscale
11015                                 // first the lightmap pass
11016                                 R_Mesh_TexBind(0, r_texture_white);
11017                                 R_Mesh_TexMatrix(0, NULL);
11018                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11019                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11020                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11021                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11022                                 else if (FAKELIGHT_ENABLED)
11023                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
11024                                 else if (rsurface.uselightmaptexture)
11025                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11026                                 else
11027                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11028                                 // then apply the texture to it
11029                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11030                                 R_Mesh_TexBind(0, layer->texture);
11031                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11032                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11033                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11034                                 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);
11035                         }
11036                         else
11037                         {
11038                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11039                                 R_Mesh_TexBind(0, layer->texture);
11040                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11041                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11042                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11043                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11044                                         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);
11045                                 else if (FAKELIGHT_ENABLED)
11046                                         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);
11047                                 else
11048                                         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);
11049                         }
11050                         break;
11051                 case TEXTURELAYERTYPE_TEXTURE:
11052                         // singletexture unlit texture with transparency support
11053                         R_Mesh_TexBind(0, layer->texture);
11054                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11055                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11056                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11057                         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);
11058                         break;
11059                 case TEXTURELAYERTYPE_FOG:
11060                         // singletexture fogging
11061                         if (layer->texture)
11062                         {
11063                                 R_Mesh_TexBind(0, layer->texture);
11064                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11065                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11066                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11067                         }
11068                         else
11069                         {
11070                                 R_Mesh_TexBind(0, 0);
11071                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11072                         }
11073                         // generate a color array for the fog pass
11074                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11075                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11076                         RSurf_DrawBatch();
11077                         break;
11078                 default:
11079                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11080                 }
11081         }
11082         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11083         {
11084                 GL_DepthFunc(GL_LEQUAL);
11085                 GL_AlphaTest(false);
11086         }
11087 }
11088
11089 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11090 {
11091         int vi;
11092         int j;
11093         r_vertexgeneric_t *batchvertex;
11094         float c[4];
11095
11096 //      R_Mesh_ResetTextureState();
11097         R_SetupShader_Generic_NoTexture(false, false);
11098
11099         if(rsurface.texture && rsurface.texture->currentskinframe)
11100         {
11101                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11102                 c[3] *= rsurface.texture->currentalpha;
11103         }
11104         else
11105         {
11106                 c[0] = 1;
11107                 c[1] = 0;
11108                 c[2] = 1;
11109                 c[3] = 1;
11110         }
11111
11112         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11113         {
11114                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11115                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11116                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11117         }
11118
11119         // brighten it up (as texture value 127 means "unlit")
11120         c[0] *= 2 * r_refdef.view.colorscale;
11121         c[1] *= 2 * r_refdef.view.colorscale;
11122         c[2] *= 2 * r_refdef.view.colorscale;
11123
11124         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11125                 c[3] *= r_wateralpha.value;
11126
11127         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11128         {
11129                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11130                 GL_DepthMask(false);
11131         }
11132         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11133         {
11134                 GL_BlendFunc(GL_ONE, GL_ONE);
11135                 GL_DepthMask(false);
11136         }
11137         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11138         {
11139                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11140                 GL_DepthMask(false);
11141         }
11142         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11143         {
11144                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11145                 GL_DepthMask(false);
11146         }
11147         else
11148         {
11149                 GL_BlendFunc(GL_ONE, GL_ZERO);
11150                 GL_DepthMask(writedepth);
11151         }
11152
11153         if (r_showsurfaces.integer == 3)
11154         {
11155                 rsurface.passcolor4f = NULL;
11156
11157                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11158                 {
11159                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11160
11161                         rsurface.passcolor4f = NULL;
11162                         rsurface.passcolor4f_vertexbuffer = 0;
11163                         rsurface.passcolor4f_bufferoffset = 0;
11164                 }
11165                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11166                 {
11167                         qboolean applycolor = true;
11168                         float one = 1.0;
11169
11170                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11171
11172                         r_refdef.lightmapintensity = 1;
11173                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11174                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11175                 }
11176                 else if (FAKELIGHT_ENABLED)
11177                 {
11178                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11179
11180                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11181                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11182                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11183                 }
11184                 else
11185                 {
11186                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11187
11188                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11189                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11190                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11191                 }
11192
11193                 if(!rsurface.passcolor4f)
11194                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11195
11196                 RSurf_DrawBatch_GL11_ApplyAmbient();
11197                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11198                 if(r_refdef.fogenabled)
11199                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11200                 RSurf_DrawBatch_GL11_ClampColor();
11201
11202                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11203                 R_SetupShader_Generic_NoTexture(false, false);
11204                 RSurf_DrawBatch();
11205         }
11206         else if (!r_refdef.view.showdebug)
11207         {
11208                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11209                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11210                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11211                 {
11212                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11213                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11214                 }
11215                 R_Mesh_PrepareVertices_Generic_Unlock();
11216                 RSurf_DrawBatch();
11217         }
11218         else if (r_showsurfaces.integer == 4)
11219         {
11220                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11221                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11222                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11223                 {
11224                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11225                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11226                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11227                 }
11228                 R_Mesh_PrepareVertices_Generic_Unlock();
11229                 RSurf_DrawBatch();
11230         }
11231         else if (r_showsurfaces.integer == 2)
11232         {
11233                 const int *e;
11234                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11235                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11236                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11237                 {
11238                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11239                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11240                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11241                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11242                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11243                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11244                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11245                 }
11246                 R_Mesh_PrepareVertices_Generic_Unlock();
11247                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11248         }
11249         else
11250         {
11251                 int texturesurfaceindex;
11252                 int k;
11253                 const msurface_t *surface;
11254                 float surfacecolor4f[4];
11255                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11256                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11257                 vi = 0;
11258                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11259                 {
11260                         surface = texturesurfacelist[texturesurfaceindex];
11261                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11262                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11263                         for (j = 0;j < surface->num_vertices;j++)
11264                         {
11265                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11266                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11267                                 vi++;
11268                         }
11269                 }
11270                 R_Mesh_PrepareVertices_Generic_Unlock();
11271                 RSurf_DrawBatch();
11272         }
11273 }
11274
11275 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11276 {
11277         CHECKGLERROR
11278         RSurf_SetupDepthAndCulling();
11279         if (r_showsurfaces.integer)
11280         {
11281                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11282                 return;
11283         }
11284         switch (vid.renderpath)
11285         {
11286         case RENDERPATH_GL20:
11287         case RENDERPATH_D3D9:
11288         case RENDERPATH_D3D10:
11289         case RENDERPATH_D3D11:
11290         case RENDERPATH_SOFT:
11291         case RENDERPATH_GLES2:
11292                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11293                 break;
11294         case RENDERPATH_GL13:
11295         case RENDERPATH_GLES1:
11296                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11297                 break;
11298         case RENDERPATH_GL11:
11299                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11300                 break;
11301         }
11302         CHECKGLERROR
11303 }
11304
11305 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11306 {
11307         CHECKGLERROR
11308         RSurf_SetupDepthAndCulling();
11309         if (r_showsurfaces.integer)
11310         {
11311                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11312                 return;
11313         }
11314         switch (vid.renderpath)
11315         {
11316         case RENDERPATH_GL20:
11317         case RENDERPATH_D3D9:
11318         case RENDERPATH_D3D10:
11319         case RENDERPATH_D3D11:
11320         case RENDERPATH_SOFT:
11321         case RENDERPATH_GLES2:
11322                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11323                 break;
11324         case RENDERPATH_GL13:
11325         case RENDERPATH_GLES1:
11326                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11327                 break;
11328         case RENDERPATH_GL11:
11329                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11330                 break;
11331         }
11332         CHECKGLERROR
11333 }
11334
11335 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11336 {
11337         int i, j;
11338         int texturenumsurfaces, endsurface;
11339         texture_t *texture;
11340         const msurface_t *surface;
11341         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11342
11343         // if the model is static it doesn't matter what value we give for
11344         // wantnormals and wanttangents, so this logic uses only rules applicable
11345         // to a model, knowing that they are meaningless otherwise
11346         if (ent == r_refdef.scene.worldentity)
11347                 RSurf_ActiveWorldEntity();
11348         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11349                 RSurf_ActiveModelEntity(ent, false, false, false);
11350         else
11351         {
11352                 switch (vid.renderpath)
11353                 {
11354                 case RENDERPATH_GL20:
11355                 case RENDERPATH_D3D9:
11356                 case RENDERPATH_D3D10:
11357                 case RENDERPATH_D3D11:
11358                 case RENDERPATH_SOFT:
11359                 case RENDERPATH_GLES2:
11360                         RSurf_ActiveModelEntity(ent, true, true, false);
11361                         break;
11362                 case RENDERPATH_GL11:
11363                 case RENDERPATH_GL13:
11364                 case RENDERPATH_GLES1:
11365                         RSurf_ActiveModelEntity(ent, true, false, false);
11366                         break;
11367                 }
11368         }
11369
11370         if (r_transparentdepthmasking.integer)
11371         {
11372                 qboolean setup = false;
11373                 for (i = 0;i < numsurfaces;i = j)
11374                 {
11375                         j = i + 1;
11376                         surface = rsurface.modelsurfaces + surfacelist[i];
11377                         texture = surface->texture;
11378                         rsurface.texture = R_GetCurrentTexture(texture);
11379                         rsurface.lightmaptexture = NULL;
11380                         rsurface.deluxemaptexture = NULL;
11381                         rsurface.uselightmaptexture = false;
11382                         // scan ahead until we find a different texture
11383                         endsurface = min(i + 1024, numsurfaces);
11384                         texturenumsurfaces = 0;
11385                         texturesurfacelist[texturenumsurfaces++] = surface;
11386                         for (;j < endsurface;j++)
11387                         {
11388                                 surface = rsurface.modelsurfaces + surfacelist[j];
11389                                 if (texture != surface->texture)
11390                                         break;
11391                                 texturesurfacelist[texturenumsurfaces++] = surface;
11392                         }
11393                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11394                                 continue;
11395                         // render the range of surfaces as depth
11396                         if (!setup)
11397                         {
11398                                 setup = true;
11399                                 GL_ColorMask(0,0,0,0);
11400                                 GL_Color(1,1,1,1);
11401                                 GL_DepthTest(true);
11402                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11403                                 GL_DepthMask(true);
11404 //                              R_Mesh_ResetTextureState();
11405                         }
11406                         RSurf_SetupDepthAndCulling();
11407                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11408                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11409                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11410                         RSurf_DrawBatch();
11411                 }
11412                 if (setup)
11413                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11414         }
11415
11416         for (i = 0;i < numsurfaces;i = j)
11417         {
11418                 j = i + 1;
11419                 surface = rsurface.modelsurfaces + surfacelist[i];
11420                 texture = surface->texture;
11421                 rsurface.texture = R_GetCurrentTexture(texture);
11422                 // scan ahead until we find a different texture
11423                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11424                 texturenumsurfaces = 0;
11425                 texturesurfacelist[texturenumsurfaces++] = surface;
11426                 if(FAKELIGHT_ENABLED)
11427                 {
11428                         rsurface.lightmaptexture = NULL;
11429                         rsurface.deluxemaptexture = NULL;
11430                         rsurface.uselightmaptexture = false;
11431                         for (;j < endsurface;j++)
11432                         {
11433                                 surface = rsurface.modelsurfaces + surfacelist[j];
11434                                 if (texture != surface->texture)
11435                                         break;
11436                                 texturesurfacelist[texturenumsurfaces++] = surface;
11437                         }
11438                 }
11439                 else
11440                 {
11441                         rsurface.lightmaptexture = surface->lightmaptexture;
11442                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11443                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11444                         for (;j < endsurface;j++)
11445                         {
11446                                 surface = rsurface.modelsurfaces + surfacelist[j];
11447                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11448                                         break;
11449                                 texturesurfacelist[texturenumsurfaces++] = surface;
11450                         }
11451                 }
11452                 // render the range of surfaces
11453                 if (ent == r_refdef.scene.worldentity)
11454                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11455                 else
11456                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11457         }
11458         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11459 }
11460
11461 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11462 {
11463         // transparent surfaces get pushed off into the transparent queue
11464         int surfacelistindex;
11465         const msurface_t *surface;
11466         vec3_t tempcenter, center;
11467         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11468         {
11469                 surface = texturesurfacelist[surfacelistindex];
11470                 if (r_transparent_sortsurfacesbynearest.integer)
11471                 {
11472                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11473                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11474                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11475                 }
11476                 else
11477                 {
11478                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11479                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11480                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11481                 }
11482                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11483                 if (rsurface.entity->transparent_offset) // transparent offset
11484                 {
11485                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11486                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11487                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11488                 }
11489                 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);
11490         }
11491 }
11492
11493 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11494 {
11495         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11496                 return;
11497         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11498                 return;
11499         RSurf_SetupDepthAndCulling();
11500         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11501         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11502         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11503         RSurf_DrawBatch();
11504 }
11505
11506 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11507 {
11508         CHECKGLERROR
11509         if (depthonly)
11510                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11511         else if (prepass)
11512         {
11513                 if (!rsurface.texture->currentnumlayers)
11514                         return;
11515                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11516                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11517                 else
11518                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11519         }
11520         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11521                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11522         else if (!rsurface.texture->currentnumlayers)
11523                 return;
11524         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11525         {
11526                 // in the deferred case, transparent surfaces were queued during prepass
11527                 if (!r_shadow_usingdeferredprepass)
11528                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11529         }
11530         else
11531         {
11532                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11533                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11534         }
11535         CHECKGLERROR
11536 }
11537
11538 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11539 {
11540         int i, j;
11541         texture_t *texture;
11542         R_FrameData_SetMark();
11543         // break the surface list down into batches by texture and use of lightmapping
11544         for (i = 0;i < numsurfaces;i = j)
11545         {
11546                 j = i + 1;
11547                 // texture is the base texture pointer, rsurface.texture is the
11548                 // current frame/skin the texture is directing us to use (for example
11549                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11550                 // use skin 1 instead)
11551                 texture = surfacelist[i]->texture;
11552                 rsurface.texture = R_GetCurrentTexture(texture);
11553                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11554                 {
11555                         // if this texture is not the kind we want, skip ahead to the next one
11556                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11557                                 ;
11558                         continue;
11559                 }
11560                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11561                 {
11562                         rsurface.lightmaptexture = NULL;
11563                         rsurface.deluxemaptexture = NULL;
11564                         rsurface.uselightmaptexture = false;
11565                         // simply scan ahead until we find a different texture or lightmap state
11566                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11567                                 ;
11568                 }
11569                 else
11570                 {
11571                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11572                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11573                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11574                         // simply scan ahead until we find a different texture or lightmap state
11575                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11576                                 ;
11577                 }
11578                 // render the range of surfaces
11579                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11580         }
11581         R_FrameData_ReturnToMark();
11582 }
11583
11584 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11585 {
11586         CHECKGLERROR
11587         if (depthonly)
11588                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11589         else if (prepass)
11590         {
11591                 if (!rsurface.texture->currentnumlayers)
11592                         return;
11593                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11594                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11595                 else
11596                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11597         }
11598         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11599                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11600         else if (!rsurface.texture->currentnumlayers)
11601                 return;
11602         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11603         {
11604                 // in the deferred case, transparent surfaces were queued during prepass
11605                 if (!r_shadow_usingdeferredprepass)
11606                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11607         }
11608         else
11609         {
11610                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11611                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11612         }
11613         CHECKGLERROR
11614 }
11615
11616 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11617 {
11618         int i, j;
11619         texture_t *texture;
11620         R_FrameData_SetMark();
11621         // break the surface list down into batches by texture and use of lightmapping
11622         for (i = 0;i < numsurfaces;i = j)
11623         {
11624                 j = i + 1;
11625                 // texture is the base texture pointer, rsurface.texture is the
11626                 // current frame/skin the texture is directing us to use (for example
11627                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11628                 // use skin 1 instead)
11629                 texture = surfacelist[i]->texture;
11630                 rsurface.texture = R_GetCurrentTexture(texture);
11631                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11632                 {
11633                         // if this texture is not the kind we want, skip ahead to the next one
11634                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11635                                 ;
11636                         continue;
11637                 }
11638                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11639                 {
11640                         rsurface.lightmaptexture = NULL;
11641                         rsurface.deluxemaptexture = NULL;
11642                         rsurface.uselightmaptexture = false;
11643                         // simply scan ahead until we find a different texture or lightmap state
11644                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11645                                 ;
11646                 }
11647                 else
11648                 {
11649                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11650                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11651                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11652                         // simply scan ahead until we find a different texture or lightmap state
11653                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11654                                 ;
11655                 }
11656                 // render the range of surfaces
11657                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11658         }
11659         R_FrameData_ReturnToMark();
11660 }
11661
11662 float locboxvertex3f[6*4*3] =
11663 {
11664         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11665         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11666         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11667         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11668         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11669         1,0,0, 0,0,0, 0,1,0, 1,1,0
11670 };
11671
11672 unsigned short locboxelements[6*2*3] =
11673 {
11674          0, 1, 2, 0, 2, 3,
11675          4, 5, 6, 4, 6, 7,
11676          8, 9,10, 8,10,11,
11677         12,13,14, 12,14,15,
11678         16,17,18, 16,18,19,
11679         20,21,22, 20,22,23
11680 };
11681
11682 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11683 {
11684         int i, j;
11685         cl_locnode_t *loc = (cl_locnode_t *)ent;
11686         vec3_t mins, size;
11687         float vertex3f[6*4*3];
11688         CHECKGLERROR
11689         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11690         GL_DepthMask(false);
11691         GL_DepthRange(0, 1);
11692         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11693         GL_DepthTest(true);
11694         GL_CullFace(GL_NONE);
11695         R_EntityMatrix(&identitymatrix);
11696
11697 //      R_Mesh_ResetTextureState();
11698
11699         i = surfacelist[0];
11700         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11701                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11702                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11703                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11704
11705         if (VectorCompare(loc->mins, loc->maxs))
11706         {
11707                 VectorSet(size, 2, 2, 2);
11708                 VectorMA(loc->mins, -0.5f, size, mins);
11709         }
11710         else
11711         {
11712                 VectorCopy(loc->mins, mins);
11713                 VectorSubtract(loc->maxs, loc->mins, size);
11714         }
11715
11716         for (i = 0;i < 6*4*3;)
11717                 for (j = 0;j < 3;j++, i++)
11718                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11719
11720         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11721         R_SetupShader_Generic_NoTexture(false, false);
11722         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11723 }
11724
11725 void R_DrawLocs(void)
11726 {
11727         int index;
11728         cl_locnode_t *loc, *nearestloc;
11729         vec3_t center;
11730         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11731         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11732         {
11733                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11734                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11735         }
11736 }
11737
11738 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11739 {
11740         if (decalsystem->decals)
11741                 Mem_Free(decalsystem->decals);
11742         memset(decalsystem, 0, sizeof(*decalsystem));
11743 }
11744
11745 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)
11746 {
11747         tridecal_t *decal;
11748         tridecal_t *decals;
11749         int i;
11750
11751         // expand or initialize the system
11752         if (decalsystem->maxdecals <= decalsystem->numdecals)
11753         {
11754                 decalsystem_t old = *decalsystem;
11755                 qboolean useshortelements;
11756                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11757                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11758                 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)));
11759                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11760                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11761                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11762                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11763                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11764                 if (decalsystem->numdecals)
11765                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11766                 if (old.decals)
11767                         Mem_Free(old.decals);
11768                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11769                         decalsystem->element3i[i] = i;
11770                 if (useshortelements)
11771                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11772                                 decalsystem->element3s[i] = i;
11773         }
11774
11775         // grab a decal and search for another free slot for the next one
11776         decals = decalsystem->decals;
11777         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11778         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11779                 ;
11780         decalsystem->freedecal = i;
11781         if (decalsystem->numdecals <= i)
11782                 decalsystem->numdecals = i + 1;
11783
11784         // initialize the decal
11785         decal->lived = 0;
11786         decal->triangleindex = triangleindex;
11787         decal->surfaceindex = surfaceindex;
11788         decal->decalsequence = decalsequence;
11789         decal->color4f[0][0] = c0[0];
11790         decal->color4f[0][1] = c0[1];
11791         decal->color4f[0][2] = c0[2];
11792         decal->color4f[0][3] = 1;
11793         decal->color4f[1][0] = c1[0];
11794         decal->color4f[1][1] = c1[1];
11795         decal->color4f[1][2] = c1[2];
11796         decal->color4f[1][3] = 1;
11797         decal->color4f[2][0] = c2[0];
11798         decal->color4f[2][1] = c2[1];
11799         decal->color4f[2][2] = c2[2];
11800         decal->color4f[2][3] = 1;
11801         decal->vertex3f[0][0] = v0[0];
11802         decal->vertex3f[0][1] = v0[1];
11803         decal->vertex3f[0][2] = v0[2];
11804         decal->vertex3f[1][0] = v1[0];
11805         decal->vertex3f[1][1] = v1[1];
11806         decal->vertex3f[1][2] = v1[2];
11807         decal->vertex3f[2][0] = v2[0];
11808         decal->vertex3f[2][1] = v2[1];
11809         decal->vertex3f[2][2] = v2[2];
11810         decal->texcoord2f[0][0] = t0[0];
11811         decal->texcoord2f[0][1] = t0[1];
11812         decal->texcoord2f[1][0] = t1[0];
11813         decal->texcoord2f[1][1] = t1[1];
11814         decal->texcoord2f[2][0] = t2[0];
11815         decal->texcoord2f[2][1] = t2[1];
11816         TriangleNormal(v0, v1, v2, decal->plane);
11817         VectorNormalize(decal->plane);
11818         decal->plane[3] = DotProduct(v0, decal->plane);
11819 }
11820
11821 extern cvar_t cl_decals_bias;
11822 extern cvar_t cl_decals_models;
11823 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11824 // baseparms, parms, temps
11825 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)
11826 {
11827         int cornerindex;
11828         int index;
11829         float v[9][3];
11830         const float *vertex3f;
11831         const float *normal3f;
11832         int numpoints;
11833         float points[2][9][3];
11834         float temp[3];
11835         float tc[9][2];
11836         float f;
11837         float c[9][4];
11838         const int *e;
11839
11840         e = rsurface.modelelement3i + 3*triangleindex;
11841
11842         vertex3f = rsurface.modelvertex3f;
11843         normal3f = rsurface.modelnormal3f;
11844
11845         if (normal3f)
11846         {
11847                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11848                 {
11849                         index = 3*e[cornerindex];
11850                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11851                 }
11852         }
11853         else
11854         {
11855                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11856                 {
11857                         index = 3*e[cornerindex];
11858                         VectorCopy(vertex3f + index, v[cornerindex]);
11859                 }
11860         }
11861
11862         // cull backfaces
11863         //TriangleNormal(v[0], v[1], v[2], normal);
11864         //if (DotProduct(normal, localnormal) < 0.0f)
11865         //      continue;
11866         // clip by each of the box planes formed from the projection matrix
11867         // if anything survives, we emit the decal
11868         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]);
11869         if (numpoints < 3)
11870                 return;
11871         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]);
11872         if (numpoints < 3)
11873                 return;
11874         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]);
11875         if (numpoints < 3)
11876                 return;
11877         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]);
11878         if (numpoints < 3)
11879                 return;
11880         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]);
11881         if (numpoints < 3)
11882                 return;
11883         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]);
11884         if (numpoints < 3)
11885                 return;
11886         // some part of the triangle survived, so we have to accept it...
11887         if (dynamic)
11888         {
11889                 // dynamic always uses the original triangle
11890                 numpoints = 3;
11891                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11892                 {
11893                         index = 3*e[cornerindex];
11894                         VectorCopy(vertex3f + index, v[cornerindex]);
11895                 }
11896         }
11897         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11898         {
11899                 // convert vertex positions to texcoords
11900                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11901                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11902                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11903                 // calculate distance fade from the projection origin
11904                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11905                 f = bound(0.0f, f, 1.0f);
11906                 c[cornerindex][0] = r * f;
11907                 c[cornerindex][1] = g * f;
11908                 c[cornerindex][2] = b * f;
11909                 c[cornerindex][3] = 1.0f;
11910                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11911         }
11912         if (dynamic)
11913                 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);
11914         else
11915                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11916                         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);
11917 }
11918 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)
11919 {
11920         matrix4x4_t projection;
11921         decalsystem_t *decalsystem;
11922         qboolean dynamic;
11923         dp_model_t *model;
11924         const msurface_t *surface;
11925         const msurface_t *surfaces;
11926         const int *surfacelist;
11927         const texture_t *texture;
11928         int numtriangles;
11929         int numsurfacelist;
11930         int surfacelistindex;
11931         int surfaceindex;
11932         int triangleindex;
11933         float localorigin[3];
11934         float localnormal[3];
11935         float localmins[3];
11936         float localmaxs[3];
11937         float localsize;
11938         //float normal[3];
11939         float planes[6][4];
11940         float angles[3];
11941         bih_t *bih;
11942         int bih_triangles_count;
11943         int bih_triangles[256];
11944         int bih_surfaces[256];
11945
11946         decalsystem = &ent->decalsystem;
11947         model = ent->model;
11948         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11949         {
11950                 R_DecalSystem_Reset(&ent->decalsystem);
11951                 return;
11952         }
11953
11954         if (!model->brush.data_leafs && !cl_decals_models.integer)
11955         {
11956                 if (decalsystem->model)
11957                         R_DecalSystem_Reset(decalsystem);
11958                 return;
11959         }
11960
11961         if (decalsystem->model != model)
11962                 R_DecalSystem_Reset(decalsystem);
11963         decalsystem->model = model;
11964
11965         RSurf_ActiveModelEntity(ent, true, false, false);
11966
11967         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11968         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11969         VectorNormalize(localnormal);
11970         localsize = worldsize*rsurface.inversematrixscale;
11971         localmins[0] = localorigin[0] - localsize;
11972         localmins[1] = localorigin[1] - localsize;
11973         localmins[2] = localorigin[2] - localsize;
11974         localmaxs[0] = localorigin[0] + localsize;
11975         localmaxs[1] = localorigin[1] + localsize;
11976         localmaxs[2] = localorigin[2] + localsize;
11977
11978         //VectorCopy(localnormal, planes[4]);
11979         //VectorVectors(planes[4], planes[2], planes[0]);
11980         AnglesFromVectors(angles, localnormal, NULL, false);
11981         AngleVectors(angles, planes[0], planes[2], planes[4]);
11982         VectorNegate(planes[0], planes[1]);
11983         VectorNegate(planes[2], planes[3]);
11984         VectorNegate(planes[4], planes[5]);
11985         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11986         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11987         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11988         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11989         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11990         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11991
11992 #if 1
11993 // works
11994 {
11995         matrix4x4_t forwardprojection;
11996         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11997         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11998 }
11999 #else
12000 // broken
12001 {
12002         float projectionvector[4][3];
12003         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12004         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12005         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12006         projectionvector[0][0] = planes[0][0] * ilocalsize;
12007         projectionvector[0][1] = planes[1][0] * ilocalsize;
12008         projectionvector[0][2] = planes[2][0] * ilocalsize;
12009         projectionvector[1][0] = planes[0][1] * ilocalsize;
12010         projectionvector[1][1] = planes[1][1] * ilocalsize;
12011         projectionvector[1][2] = planes[2][1] * ilocalsize;
12012         projectionvector[2][0] = planes[0][2] * ilocalsize;
12013         projectionvector[2][1] = planes[1][2] * ilocalsize;
12014         projectionvector[2][2] = planes[2][2] * ilocalsize;
12015         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12016         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12017         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12018         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12019 }
12020 #endif
12021
12022         dynamic = model->surfmesh.isanimated;
12023         numsurfacelist = model->nummodelsurfaces;
12024         surfacelist = model->sortedmodelsurfaces;
12025         surfaces = model->data_surfaces;
12026
12027         bih = NULL;
12028         bih_triangles_count = -1;
12029         if(!dynamic)
12030         {
12031                 if(model->render_bih.numleafs)
12032                         bih = &model->render_bih;
12033                 else if(model->collision_bih.numleafs)
12034                         bih = &model->collision_bih;
12035         }
12036         if(bih)
12037                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12038         if(bih_triangles_count == 0)
12039                 return;
12040         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12041                 return;
12042         if(bih_triangles_count > 0)
12043         {
12044                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12045                 {
12046                         surfaceindex = bih_surfaces[triangleindex];
12047                         surface = surfaces + surfaceindex;
12048                         texture = surface->texture;
12049                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12050                                 continue;
12051                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12052                                 continue;
12053                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12054                 }
12055         }
12056         else
12057         {
12058                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12059                 {
12060                         surfaceindex = surfacelist[surfacelistindex];
12061                         surface = surfaces + surfaceindex;
12062                         // check cull box first because it rejects more than any other check
12063                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12064                                 continue;
12065                         // skip transparent surfaces
12066                         texture = surface->texture;
12067                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12068                                 continue;
12069                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12070                                 continue;
12071                         numtriangles = surface->num_triangles;
12072                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12073                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12074                 }
12075         }
12076 }
12077
12078 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12079 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)
12080 {
12081         int renderentityindex;
12082         float worldmins[3];
12083         float worldmaxs[3];
12084         entity_render_t *ent;
12085
12086         if (!cl_decals_newsystem.integer)
12087                 return;
12088
12089         worldmins[0] = worldorigin[0] - worldsize;
12090         worldmins[1] = worldorigin[1] - worldsize;
12091         worldmins[2] = worldorigin[2] - worldsize;
12092         worldmaxs[0] = worldorigin[0] + worldsize;
12093         worldmaxs[1] = worldorigin[1] + worldsize;
12094         worldmaxs[2] = worldorigin[2] + worldsize;
12095
12096         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12097
12098         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12099         {
12100                 ent = r_refdef.scene.entities[renderentityindex];
12101                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12102                         continue;
12103
12104                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12105         }
12106 }
12107
12108 typedef struct r_decalsystem_splatqueue_s
12109 {
12110         vec3_t worldorigin;
12111         vec3_t worldnormal;
12112         float color[4];
12113         float tcrange[4];
12114         float worldsize;
12115         unsigned int decalsequence;
12116 }
12117 r_decalsystem_splatqueue_t;
12118
12119 int r_decalsystem_numqueued = 0;
12120 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12121
12122 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)
12123 {
12124         r_decalsystem_splatqueue_t *queue;
12125
12126         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12127                 return;
12128
12129         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12130         VectorCopy(worldorigin, queue->worldorigin);
12131         VectorCopy(worldnormal, queue->worldnormal);
12132         Vector4Set(queue->color, r, g, b, a);
12133         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12134         queue->worldsize = worldsize;
12135         queue->decalsequence = cl.decalsequence++;
12136 }
12137
12138 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12139 {
12140         int i;
12141         r_decalsystem_splatqueue_t *queue;
12142
12143         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12144                 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);
12145         r_decalsystem_numqueued = 0;
12146 }
12147
12148 extern cvar_t cl_decals_max;
12149 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12150 {
12151         int i;
12152         decalsystem_t *decalsystem = &ent->decalsystem;
12153         int numdecals;
12154         unsigned int killsequence;
12155         tridecal_t *decal;
12156         float frametime;
12157         float lifetime;
12158
12159         if (!decalsystem->numdecals)
12160                 return;
12161
12162         if (r_showsurfaces.integer)
12163                 return;
12164
12165         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12166         {
12167                 R_DecalSystem_Reset(decalsystem);
12168                 return;
12169         }
12170
12171         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12172         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12173
12174         if (decalsystem->lastupdatetime)
12175                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12176         else
12177                 frametime = 0;
12178         decalsystem->lastupdatetime = r_refdef.scene.time;
12179         numdecals = decalsystem->numdecals;
12180
12181         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12182         {
12183                 if (decal->color4f[0][3])
12184                 {
12185                         decal->lived += frametime;
12186                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12187                         {
12188                                 memset(decal, 0, sizeof(*decal));
12189                                 if (decalsystem->freedecal > i)
12190                                         decalsystem->freedecal = i;
12191                         }
12192                 }
12193         }
12194         decal = decalsystem->decals;
12195         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12196                 numdecals--;
12197
12198         // collapse the array by shuffling the tail decals into the gaps
12199         for (;;)
12200         {
12201                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12202                         decalsystem->freedecal++;
12203                 if (decalsystem->freedecal == numdecals)
12204                         break;
12205                 decal[decalsystem->freedecal] = decal[--numdecals];
12206         }
12207
12208         decalsystem->numdecals = numdecals;
12209
12210         if (numdecals <= 0)
12211         {
12212                 // if there are no decals left, reset decalsystem
12213                 R_DecalSystem_Reset(decalsystem);
12214         }
12215 }
12216
12217 extern skinframe_t *decalskinframe;
12218 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12219 {
12220         int i;
12221         decalsystem_t *decalsystem = &ent->decalsystem;
12222         int numdecals;
12223         tridecal_t *decal;
12224         float faderate;
12225         float alpha;
12226         float *v3f;
12227         float *c4f;
12228         float *t2f;
12229         const int *e;
12230         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12231         int numtris = 0;
12232
12233         numdecals = decalsystem->numdecals;
12234         if (!numdecals)
12235                 return;
12236
12237         if (r_showsurfaces.integer)
12238                 return;
12239
12240         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12241         {
12242                 R_DecalSystem_Reset(decalsystem);
12243                 return;
12244         }
12245
12246         // if the model is static it doesn't matter what value we give for
12247         // wantnormals and wanttangents, so this logic uses only rules applicable
12248         // to a model, knowing that they are meaningless otherwise
12249         if (ent == r_refdef.scene.worldentity)
12250                 RSurf_ActiveWorldEntity();
12251         else
12252                 RSurf_ActiveModelEntity(ent, false, false, false);
12253
12254         decalsystem->lastupdatetime = r_refdef.scene.time;
12255
12256         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12257
12258         // update vertex positions for animated models
12259         v3f = decalsystem->vertex3f;
12260         c4f = decalsystem->color4f;
12261         t2f = decalsystem->texcoord2f;
12262         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12263         {
12264                 if (!decal->color4f[0][3])
12265                         continue;
12266
12267                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12268                         continue;
12269
12270                 // skip backfaces
12271                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12272                         continue;
12273
12274                 // update color values for fading decals
12275                 if (decal->lived >= cl_decals_time.value)
12276                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12277                 else
12278                         alpha = 1.0f;
12279
12280                 c4f[ 0] = decal->color4f[0][0] * alpha;
12281                 c4f[ 1] = decal->color4f[0][1] * alpha;
12282                 c4f[ 2] = decal->color4f[0][2] * alpha;
12283                 c4f[ 3] = 1;
12284                 c4f[ 4] = decal->color4f[1][0] * alpha;
12285                 c4f[ 5] = decal->color4f[1][1] * alpha;
12286                 c4f[ 6] = decal->color4f[1][2] * alpha;
12287                 c4f[ 7] = 1;
12288                 c4f[ 8] = decal->color4f[2][0] * alpha;
12289                 c4f[ 9] = decal->color4f[2][1] * alpha;
12290                 c4f[10] = decal->color4f[2][2] * alpha;
12291                 c4f[11] = 1;
12292
12293                 t2f[0] = decal->texcoord2f[0][0];
12294                 t2f[1] = decal->texcoord2f[0][1];
12295                 t2f[2] = decal->texcoord2f[1][0];
12296                 t2f[3] = decal->texcoord2f[1][1];
12297                 t2f[4] = decal->texcoord2f[2][0];
12298                 t2f[5] = decal->texcoord2f[2][1];
12299
12300                 // update vertex positions for animated models
12301                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12302                 {
12303                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12304                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12305                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12306                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12307                 }
12308                 else
12309                 {
12310                         VectorCopy(decal->vertex3f[0], v3f);
12311                         VectorCopy(decal->vertex3f[1], v3f + 3);
12312                         VectorCopy(decal->vertex3f[2], v3f + 6);
12313                 }
12314
12315                 if (r_refdef.fogenabled)
12316                 {
12317                         alpha = RSurf_FogVertex(v3f);
12318                         VectorScale(c4f, alpha, c4f);
12319                         alpha = RSurf_FogVertex(v3f + 3);
12320                         VectorScale(c4f + 4, alpha, c4f + 4);
12321                         alpha = RSurf_FogVertex(v3f + 6);
12322                         VectorScale(c4f + 8, alpha, c4f + 8);
12323                 }
12324
12325                 v3f += 9;
12326                 c4f += 12;
12327                 t2f += 6;
12328                 numtris++;
12329         }
12330
12331         if (numtris > 0)
12332         {
12333                 r_refdef.stats[r_stat_drawndecals] += numtris;
12334
12335                 // now render the decals all at once
12336                 // (this assumes they all use one particle font texture!)
12337                 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);
12338 //              R_Mesh_ResetTextureState();
12339                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12340                 GL_DepthMask(false);
12341                 GL_DepthRange(0, 1);
12342                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12343                 GL_DepthTest(true);
12344                 GL_CullFace(GL_NONE);
12345                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12346                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12347                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12348         }
12349 }
12350
12351 static void R_DrawModelDecals(void)
12352 {
12353         int i, numdecals;
12354
12355         // fade faster when there are too many decals
12356         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12357         for (i = 0;i < r_refdef.scene.numentities;i++)
12358                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12359
12360         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12361         for (i = 0;i < r_refdef.scene.numentities;i++)
12362                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12363                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12364
12365         R_DecalSystem_ApplySplatEntitiesQueue();
12366
12367         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12368         for (i = 0;i < r_refdef.scene.numentities;i++)
12369                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12370
12371         r_refdef.stats[r_stat_totaldecals] += numdecals;
12372
12373         if (r_showsurfaces.integer)
12374                 return;
12375
12376         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12377
12378         for (i = 0;i < r_refdef.scene.numentities;i++)
12379         {
12380                 if (!r_refdef.viewcache.entityvisible[i])
12381                         continue;
12382                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12383                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12384         }
12385 }
12386
12387 extern cvar_t mod_collision_bih;
12388 static void R_DrawDebugModel(void)
12389 {
12390         entity_render_t *ent = rsurface.entity;
12391         int i, j, flagsmask;
12392         const msurface_t *surface;
12393         dp_model_t *model = ent->model;
12394
12395         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12396                 return;
12397
12398         if (r_showoverdraw.value > 0)
12399         {
12400                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12401                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12402                 R_SetupShader_Generic_NoTexture(false, false);
12403                 GL_DepthTest(false);
12404                 GL_DepthMask(false);
12405                 GL_DepthRange(0, 1);
12406                 GL_BlendFunc(GL_ONE, GL_ONE);
12407                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12408                 {
12409                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12410                                 continue;
12411                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12412                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12413                         {
12414                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12415                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12416                                 if (!rsurface.texture->currentlayers->depthmask)
12417                                         GL_Color(c, 0, 0, 1.0f);
12418                                 else if (ent == r_refdef.scene.worldentity)
12419                                         GL_Color(c, c, c, 1.0f);
12420                                 else
12421                                         GL_Color(0, c, 0, 1.0f);
12422                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12423                                 RSurf_DrawBatch();
12424                         }
12425                 }
12426                 rsurface.texture = NULL;
12427         }
12428
12429         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12430
12431 //      R_Mesh_ResetTextureState();
12432         R_SetupShader_Generic_NoTexture(false, false);
12433         GL_DepthRange(0, 1);
12434         GL_DepthTest(!r_showdisabledepthtest.integer);
12435         GL_DepthMask(false);
12436         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12437
12438         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12439         {
12440                 int triangleindex;
12441                 int bihleafindex;
12442                 qboolean cullbox = false;
12443                 const q3mbrush_t *brush;
12444                 const bih_t *bih = &model->collision_bih;
12445                 const bih_leaf_t *bihleaf;
12446                 float vertex3f[3][3];
12447                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12448                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12449                 {
12450                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12451                                 continue;
12452                         switch (bihleaf->type)
12453                         {
12454                         case BIH_BRUSH:
12455                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12456                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12457                                 {
12458                                         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);
12459                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12460                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12461                                 }
12462                                 break;
12463                         case BIH_COLLISIONTRIANGLE:
12464                                 triangleindex = bihleaf->itemindex;
12465                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12466                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12467                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12468                                 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);
12469                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12470                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12471                                 break;
12472                         case BIH_RENDERTRIANGLE:
12473                                 triangleindex = bihleaf->itemindex;
12474                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12475                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12476                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12477                                 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);
12478                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12479                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12480                                 break;
12481                         }
12482                 }
12483         }
12484
12485         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12486
12487 #ifndef USE_GLES2
12488         if (r_showtris.integer && qglPolygonMode)
12489         {
12490                 if (r_showdisabledepthtest.integer)
12491                 {
12492                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12493                         GL_DepthMask(false);
12494                 }
12495                 else
12496                 {
12497                         GL_BlendFunc(GL_ONE, GL_ZERO);
12498                         GL_DepthMask(true);
12499                 }
12500                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12501                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12502                 {
12503                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12504                                 continue;
12505                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12506                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12507                         {
12508                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12509                                 if (!rsurface.texture->currentlayers->depthmask)
12510                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12511                                 else if (ent == r_refdef.scene.worldentity)
12512                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12513                                 else
12514                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12515                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12516                                 RSurf_DrawBatch();
12517                         }
12518                 }
12519                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12520                 rsurface.texture = NULL;
12521         }
12522
12523         if (r_shownormals.value != 0 && qglBegin)
12524         {
12525                 int l, k;
12526                 vec3_t v;
12527                 if (r_showdisabledepthtest.integer)
12528                 {
12529                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12530                         GL_DepthMask(false);
12531                 }
12532                 else
12533                 {
12534                         GL_BlendFunc(GL_ONE, GL_ZERO);
12535                         GL_DepthMask(true);
12536                 }
12537                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12538                 {
12539                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12540                                 continue;
12541                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12542                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12543                         {
12544                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12545                                 qglBegin(GL_LINES);
12546                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12547                                 {
12548                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12549                                         {
12550                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12551                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12552                                                 qglVertex3f(v[0], v[1], v[2]);
12553                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12554                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12555                                                 qglVertex3f(v[0], v[1], v[2]);
12556                                         }
12557                                 }
12558                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12559                                 {
12560                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12561                                         {
12562                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12563                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12564                                                 qglVertex3f(v[0], v[1], v[2]);
12565                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12566                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12567                                                 qglVertex3f(v[0], v[1], v[2]);
12568                                         }
12569                                 }
12570                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12571                                 {
12572                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12573                                         {
12574                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12575                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12576                                                 qglVertex3f(v[0], v[1], v[2]);
12577                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12578                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12579                                                 qglVertex3f(v[0], v[1], v[2]);
12580                                         }
12581                                 }
12582                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12583                                 {
12584                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12585                                         {
12586                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12587                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12588                                                 qglVertex3f(v[0], v[1], v[2]);
12589                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12590                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12591                                                 qglVertex3f(v[0], v[1], v[2]);
12592                                         }
12593                                 }
12594                                 qglEnd();
12595                                 CHECKGLERROR
12596                         }
12597                 }
12598                 rsurface.texture = NULL;
12599         }
12600 #endif
12601 }
12602
12603 int r_maxsurfacelist = 0;
12604 const msurface_t **r_surfacelist = NULL;
12605 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12606 {
12607         int i, j, endj, flagsmask;
12608         dp_model_t *model = r_refdef.scene.worldmodel;
12609         msurface_t *surfaces;
12610         unsigned char *update;
12611         int numsurfacelist = 0;
12612         if (model == NULL)
12613                 return;
12614
12615         if (r_maxsurfacelist < model->num_surfaces)
12616         {
12617                 r_maxsurfacelist = model->num_surfaces;
12618                 if (r_surfacelist)
12619                         Mem_Free((msurface_t**)r_surfacelist);
12620                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12621         }
12622
12623         RSurf_ActiveWorldEntity();
12624
12625         surfaces = model->data_surfaces;
12626         update = model->brushq1.lightmapupdateflags;
12627
12628         // update light styles on this submodel
12629         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12630         {
12631                 model_brush_lightstyleinfo_t *style;
12632                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12633                 {
12634                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12635                         {
12636                                 int *list = style->surfacelist;
12637                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12638                                 for (j = 0;j < style->numsurfaces;j++)
12639                                         update[list[j]] = true;
12640                         }
12641                 }
12642         }
12643
12644         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12645
12646         if (debug)
12647         {
12648                 R_DrawDebugModel();
12649                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12650                 return;
12651         }
12652
12653         rsurface.lightmaptexture = NULL;
12654         rsurface.deluxemaptexture = NULL;
12655         rsurface.uselightmaptexture = false;
12656         rsurface.texture = NULL;
12657         rsurface.rtlight = NULL;
12658         numsurfacelist = 0;
12659         // add visible surfaces to draw list
12660         for (i = 0;i < model->nummodelsurfaces;i++)
12661         {
12662                 j = model->sortedmodelsurfaces[i];
12663                 if (r_refdef.viewcache.world_surfacevisible[j])
12664                         r_surfacelist[numsurfacelist++] = surfaces + j;
12665         }
12666         // update lightmaps if needed
12667         if (model->brushq1.firstrender)
12668         {
12669                 model->brushq1.firstrender = false;
12670                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12671                         if (update[j])
12672                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12673         }
12674         else if (update)
12675         {
12676                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12677                         if (r_refdef.viewcache.world_surfacevisible[j])
12678                                 if (update[j])
12679                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12680         }
12681         // don't do anything if there were no surfaces
12682         if (!numsurfacelist)
12683         {
12684                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12685                 return;
12686         }
12687         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12688
12689         // add to stats if desired
12690         if (r_speeds.integer && !skysurfaces && !depthonly)
12691         {
12692                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12693                 for (j = 0;j < numsurfacelist;j++)
12694                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12695         }
12696
12697         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12698 }
12699
12700 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12701 {
12702         int i, j, endj, flagsmask;
12703         dp_model_t *model = ent->model;
12704         msurface_t *surfaces;
12705         unsigned char *update;
12706         int numsurfacelist = 0;
12707         if (model == NULL)
12708                 return;
12709
12710         if (r_maxsurfacelist < model->num_surfaces)
12711         {
12712                 r_maxsurfacelist = model->num_surfaces;
12713                 if (r_surfacelist)
12714                         Mem_Free((msurface_t **)r_surfacelist);
12715                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12716         }
12717
12718         // if the model is static it doesn't matter what value we give for
12719         // wantnormals and wanttangents, so this logic uses only rules applicable
12720         // to a model, knowing that they are meaningless otherwise
12721         if (ent == r_refdef.scene.worldentity)
12722                 RSurf_ActiveWorldEntity();
12723         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12724                 RSurf_ActiveModelEntity(ent, false, false, false);
12725         else if (prepass)
12726                 RSurf_ActiveModelEntity(ent, true, true, true);
12727         else if (depthonly)
12728         {
12729                 switch (vid.renderpath)
12730                 {
12731                 case RENDERPATH_GL20:
12732                 case RENDERPATH_D3D9:
12733                 case RENDERPATH_D3D10:
12734                 case RENDERPATH_D3D11:
12735                 case RENDERPATH_SOFT:
12736                 case RENDERPATH_GLES2:
12737                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12738                         break;
12739                 case RENDERPATH_GL11:
12740                 case RENDERPATH_GL13:
12741                 case RENDERPATH_GLES1:
12742                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12743                         break;
12744                 }
12745         }
12746         else
12747         {
12748                 switch (vid.renderpath)
12749                 {
12750                 case RENDERPATH_GL20:
12751                 case RENDERPATH_D3D9:
12752                 case RENDERPATH_D3D10:
12753                 case RENDERPATH_D3D11:
12754                 case RENDERPATH_SOFT:
12755                 case RENDERPATH_GLES2:
12756                         RSurf_ActiveModelEntity(ent, true, true, false);
12757                         break;
12758                 case RENDERPATH_GL11:
12759                 case RENDERPATH_GL13:
12760                 case RENDERPATH_GLES1:
12761                         RSurf_ActiveModelEntity(ent, true, false, false);
12762                         break;
12763                 }
12764         }
12765
12766         surfaces = model->data_surfaces;
12767         update = model->brushq1.lightmapupdateflags;
12768
12769         // update light styles
12770         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12771         {
12772                 model_brush_lightstyleinfo_t *style;
12773                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12774                 {
12775                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12776                         {
12777                                 int *list = style->surfacelist;
12778                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12779                                 for (j = 0;j < style->numsurfaces;j++)
12780                                         update[list[j]] = true;
12781                         }
12782                 }
12783         }
12784
12785         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12786
12787         if (debug)
12788         {
12789                 R_DrawDebugModel();
12790                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12791                 return;
12792         }
12793
12794         rsurface.lightmaptexture = NULL;
12795         rsurface.deluxemaptexture = NULL;
12796         rsurface.uselightmaptexture = false;
12797         rsurface.texture = NULL;
12798         rsurface.rtlight = NULL;
12799         numsurfacelist = 0;
12800         // add visible surfaces to draw list
12801         for (i = 0;i < model->nummodelsurfaces;i++)
12802                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12803         // don't do anything if there were no surfaces
12804         if (!numsurfacelist)
12805         {
12806                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12807                 return;
12808         }
12809         // update lightmaps if needed
12810         if (update)
12811         {
12812                 int updated = 0;
12813                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12814                 {
12815                         if (update[j])
12816                         {
12817                                 updated++;
12818                                 R_BuildLightMap(ent, surfaces + j);
12819                         }
12820                 }
12821         }
12822
12823         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12824
12825         // add to stats if desired
12826         if (r_speeds.integer && !skysurfaces && !depthonly)
12827         {
12828                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12829                 for (j = 0;j < numsurfacelist;j++)
12830                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12831         }
12832
12833         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12834 }
12835
12836 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12837 {
12838         static texture_t texture;
12839         static msurface_t surface;
12840         const msurface_t *surfacelist = &surface;
12841
12842         // fake enough texture and surface state to render this geometry
12843
12844         texture.update_lastrenderframe = -1; // regenerate this texture
12845         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12846         texture.basealpha = 1.0f;
12847         texture.currentskinframe = skinframe;
12848         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12849         texture.offsetmapping = OFFSETMAPPING_OFF;
12850         texture.offsetscale = 1;
12851         texture.specularscalemod = 1;
12852         texture.specularpowermod = 1;
12853         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12854         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12855         // JUST GREP FOR "specularscalemod = 1".
12856
12857         surface.texture = &texture;
12858         surface.num_triangles = numtriangles;
12859         surface.num_firsttriangle = firsttriangle;
12860         surface.num_vertices = numvertices;
12861         surface.num_firstvertex = firstvertex;
12862
12863         // now render it
12864         rsurface.texture = R_GetCurrentTexture(surface.texture);
12865         rsurface.lightmaptexture = NULL;
12866         rsurface.deluxemaptexture = NULL;
12867         rsurface.uselightmaptexture = false;
12868         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12869 }
12870
12871 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)
12872 {
12873         static msurface_t surface;
12874         const msurface_t *surfacelist = &surface;
12875
12876         // fake enough texture and surface state to render this geometry
12877         surface.texture = texture;
12878         surface.num_triangles = numtriangles;
12879         surface.num_firsttriangle = firsttriangle;
12880         surface.num_vertices = numvertices;
12881         surface.num_firstvertex = firstvertex;
12882
12883         // now render it
12884         rsurface.texture = R_GetCurrentTexture(surface.texture);
12885         rsurface.lightmaptexture = NULL;
12886         rsurface.deluxemaptexture = NULL;
12887         rsurface.uselightmaptexture = false;
12888         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12889 }