]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Fix a couple warnings for unused variables in listdirectory on WIN32.
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 #ifdef WIN32
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
43 #ifdef __cplusplus
44 }
45 #endif
46 #endif
47
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
50
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
52
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
55 qboolean r_loadfog;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
59
60 //
61 // screen size info
62 //
63 r_refdef_t r_refdef;
64
65 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!"};
66 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!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 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)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 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"};
72 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"};
73 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"};
74 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"};
75 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"};
76 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"};
77
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 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"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
81 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)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
83
84 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"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 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"};
92 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"};
93 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"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
96 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)"};
97 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
98 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
99 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"};
100 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"};
101 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
102 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"};
103 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"};
104 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"};
105 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
106 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
107 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
108 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
109 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
110 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
111 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
112 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)"};
113 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)"};
114 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
115 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
116 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
117 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
118 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
119
120 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
121 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
122 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
123
124 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
125 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
126 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
127 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."};
128 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
129 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
130 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
131 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."};
132 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
133 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
134 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
135 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."};
136 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
137 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"};
138 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"};
139 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
140 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
141 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
142 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
143 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
144 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"};
145 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
146 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
147 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
148 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
149 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
150
151 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
152 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
153 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
154 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
155 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
156 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
157 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
158 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
159
160 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)"};
161 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"};
162
163 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
164 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
165 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
166
167 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"};
168 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"};
169 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"};
170 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
171 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
172 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"};
173 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)"};
174 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)"};
175 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
176
177 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
178 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)"};
179 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
180 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)"};
181 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
182 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)"};
183 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)"};
184 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
185 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"};
186 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."};
187 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
188 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)"};
189 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)"};
190 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)"};
191 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)"};
192 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)"};
193 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)"};
194 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)"};
195 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)"};
196
197 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)"};
198 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)"};
199 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
200 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"};
201 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
202 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
203 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
204 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"};
205 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"};
206 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)"};
207
208 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
209 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
210 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
211 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
212
213 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
214 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
215
216 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
217 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
218 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
219 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
220 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
221 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
222
223 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
224 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
225 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
226 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
227 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
228 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
229 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
230 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
231 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
232 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
233
234 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"};
235
236 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"};
237
238 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
239
240 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
241
242 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)"};
243 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)"};
244 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
245 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
246
247 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
248 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"};
249
250 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."};
251
252 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)"};
253 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
254 {
255         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
256         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
257         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
258         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
259 };
260
261 extern cvar_t v_glslgamma;
262 extern cvar_t v_glslgamma_2d;
263
264 extern qboolean v_flipped_state;
265
266 r_framebufferstate_t r_fb;
267
268 /// shadow volume bsp struct with automatically growing nodes buffer
269 svbsp_t r_svbsp;
270
271 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
272
273 rtexture_t *r_texture_blanknormalmap;
274 rtexture_t *r_texture_white;
275 rtexture_t *r_texture_grey128;
276 rtexture_t *r_texture_black;
277 rtexture_t *r_texture_notexture;
278 rtexture_t *r_texture_whitecube;
279 rtexture_t *r_texture_normalizationcube;
280 rtexture_t *r_texture_fogattenuation;
281 rtexture_t *r_texture_fogheighttexture;
282 rtexture_t *r_texture_gammaramps;
283 unsigned int r_texture_gammaramps_serial;
284 //rtexture_t *r_texture_fogintensity;
285 rtexture_t *r_texture_reflectcube;
286
287 // TODO: hash lookups?
288 typedef struct cubemapinfo_s
289 {
290         char basename[64];
291         rtexture_t *texture;
292 }
293 cubemapinfo_t;
294
295 int r_texture_numcubemaps;
296 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
297
298 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
299 unsigned int r_numqueries;
300 unsigned int r_maxqueries;
301
302 typedef struct r_qwskincache_s
303 {
304         char name[MAX_QPATH];
305         skinframe_t *skinframe;
306 }
307 r_qwskincache_t;
308
309 static r_qwskincache_t *r_qwskincache;
310 static int r_qwskincache_size;
311
312 /// vertex coordinates for a quad that covers the screen exactly
313 extern const float r_screenvertex3f[12];
314 extern const float r_d3dscreenvertex3f[12];
315 const float r_screenvertex3f[12] =
316 {
317         0, 0, 0,
318         1, 0, 0,
319         1, 1, 0,
320         0, 1, 0
321 };
322 const float r_d3dscreenvertex3f[12] =
323 {
324         0, 1, 0,
325         1, 1, 0,
326         1, 0, 0,
327         0, 0, 0
328 };
329
330 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
331 {
332         int i;
333         for (i = 0;i < verts;i++)
334         {
335                 out[0] = in[0] * r;
336                 out[1] = in[1] * g;
337                 out[2] = in[2] * b;
338                 out[3] = in[3];
339                 in += 4;
340                 out += 4;
341         }
342 }
343
344 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
345 {
346         int i;
347         for (i = 0;i < verts;i++)
348         {
349                 out[0] = r;
350                 out[1] = g;
351                 out[2] = b;
352                 out[3] = a;
353                 out += 4;
354         }
355 }
356
357 // FIXME: move this to client?
358 void FOG_clear(void)
359 {
360         if (gamemode == GAME_NEHAHRA)
361         {
362                 Cvar_Set("gl_fogenable", "0");
363                 Cvar_Set("gl_fogdensity", "0.2");
364                 Cvar_Set("gl_fogred", "0.3");
365                 Cvar_Set("gl_foggreen", "0.3");
366                 Cvar_Set("gl_fogblue", "0.3");
367         }
368         r_refdef.fog_density = 0;
369         r_refdef.fog_red = 0;
370         r_refdef.fog_green = 0;
371         r_refdef.fog_blue = 0;
372         r_refdef.fog_alpha = 1;
373         r_refdef.fog_start = 0;
374         r_refdef.fog_end = 16384;
375         r_refdef.fog_height = 1<<30;
376         r_refdef.fog_fadedepth = 128;
377         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
378 }
379
380 static void R_BuildBlankTextures(void)
381 {
382         unsigned char data[4];
383         data[2] = 128; // normal X
384         data[1] = 128; // normal Y
385         data[0] = 255; // normal Z
386         data[3] = 255; // height
387         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388         data[0] = 255;
389         data[1] = 255;
390         data[2] = 255;
391         data[3] = 255;
392         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393         data[0] = 128;
394         data[1] = 128;
395         data[2] = 128;
396         data[3] = 255;
397         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
398         data[0] = 0;
399         data[1] = 0;
400         data[2] = 0;
401         data[3] = 255;
402         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildNoTexture(void)
406 {
407         int x, y;
408         unsigned char pix[16][16][4];
409         // this makes a light grey/dark grey checkerboard texture
410         for (y = 0;y < 16;y++)
411         {
412                 for (x = 0;x < 16;x++)
413                 {
414                         if ((y < 8) ^ (x < 8))
415                         {
416                                 pix[y][x][0] = 128;
417                                 pix[y][x][1] = 128;
418                                 pix[y][x][2] = 128;
419                                 pix[y][x][3] = 255;
420                         }
421                         else
422                         {
423                                 pix[y][x][0] = 64;
424                                 pix[y][x][1] = 64;
425                                 pix[y][x][2] = 64;
426                                 pix[y][x][3] = 255;
427                         }
428                 }
429         }
430         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
431 }
432
433 static void R_BuildWhiteCube(void)
434 {
435         unsigned char data[6*1*1*4];
436         memset(data, 255, sizeof(data));
437         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
438 }
439
440 static void R_BuildNormalizationCube(void)
441 {
442         int x, y, side;
443         vec3_t v;
444         vec_t s, t, intensity;
445 #define NORMSIZE 64
446         unsigned char *data;
447         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
448         for (side = 0;side < 6;side++)
449         {
450                 for (y = 0;y < NORMSIZE;y++)
451                 {
452                         for (x = 0;x < NORMSIZE;x++)
453                         {
454                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
455                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
456                                 switch(side)
457                                 {
458                                 default:
459                                 case 0:
460                                         v[0] = 1;
461                                         v[1] = -t;
462                                         v[2] = -s;
463                                         break;
464                                 case 1:
465                                         v[0] = -1;
466                                         v[1] = -t;
467                                         v[2] = s;
468                                         break;
469                                 case 2:
470                                         v[0] = s;
471                                         v[1] = 1;
472                                         v[2] = t;
473                                         break;
474                                 case 3:
475                                         v[0] = s;
476                                         v[1] = -1;
477                                         v[2] = -t;
478                                         break;
479                                 case 4:
480                                         v[0] = s;
481                                         v[1] = -t;
482                                         v[2] = 1;
483                                         break;
484                                 case 5:
485                                         v[0] = -s;
486                                         v[1] = -t;
487                                         v[2] = -1;
488                                         break;
489                                 }
490                                 intensity = 127.0f / sqrt(DotProduct(v, v));
491                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
492                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
493                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
494                                 data[((side*64+y)*64+x)*4+3] = 255;
495                         }
496                 }
497         }
498         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
499         Mem_Free(data);
500 }
501
502 static void R_BuildFogTexture(void)
503 {
504         int x, b;
505 #define FOGWIDTH 256
506         unsigned char data1[FOGWIDTH][4];
507         //unsigned char data2[FOGWIDTH][4];
508         double d, r, alpha;
509
510         r_refdef.fogmasktable_start = r_refdef.fog_start;
511         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
512         r_refdef.fogmasktable_range = r_refdef.fogrange;
513         r_refdef.fogmasktable_density = r_refdef.fog_density;
514
515         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
516         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
517         {
518                 d = (x * r - r_refdef.fogmasktable_start);
519                 if(developer_extra.integer)
520                         Con_DPrintf("%f ", d);
521                 d = max(0, d);
522                 if (r_fog_exp2.integer)
523                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
524                 else
525                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
526                 if(developer_extra.integer)
527                         Con_DPrintf(" : %f ", alpha);
528                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
529                 if(developer_extra.integer)
530                         Con_DPrintf(" = %f\n", alpha);
531                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
532         }
533
534         for (x = 0;x < FOGWIDTH;x++)
535         {
536                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
537                 data1[x][0] = b;
538                 data1[x][1] = b;
539                 data1[x][2] = b;
540                 data1[x][3] = 255;
541                 //data2[x][0] = 255 - b;
542                 //data2[x][1] = 255 - b;
543                 //data2[x][2] = 255 - b;
544                 //data2[x][3] = 255;
545         }
546         if (r_texture_fogattenuation)
547         {
548                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
549                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
550         }
551         else
552         {
553                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
554                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
555         }
556 }
557
558 static void R_BuildFogHeightTexture(void)
559 {
560         unsigned char *inpixels;
561         int size;
562         int x;
563         int y;
564         int j;
565         float c[4];
566         float f;
567         inpixels = NULL;
568         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
569         if (r_refdef.fogheighttexturename[0])
570                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
571         if (!inpixels)
572         {
573                 r_refdef.fog_height_tablesize = 0;
574                 if (r_texture_fogheighttexture)
575                         R_FreeTexture(r_texture_fogheighttexture);
576                 r_texture_fogheighttexture = NULL;
577                 if (r_refdef.fog_height_table2d)
578                         Mem_Free(r_refdef.fog_height_table2d);
579                 r_refdef.fog_height_table2d = NULL;
580                 if (r_refdef.fog_height_table1d)
581                         Mem_Free(r_refdef.fog_height_table1d);
582                 r_refdef.fog_height_table1d = NULL;
583                 return;
584         }
585         size = image_width;
586         r_refdef.fog_height_tablesize = size;
587         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
588         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
589         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
590         Mem_Free(inpixels);
591         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
592         // average fog color table accounting for every fog layer between a point
593         // and the camera.  (Note: attenuation is handled separately!)
594         for (y = 0;y < size;y++)
595         {
596                 for (x = 0;x < size;x++)
597                 {
598                         Vector4Clear(c);
599                         f = 0;
600                         if (x < y)
601                         {
602                                 for (j = x;j <= y;j++)
603                                 {
604                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605                                         f++;
606                                 }
607                         }
608                         else
609                         {
610                                 for (j = x;j >= y;j--)
611                                 {
612                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
613                                         f++;
614                                 }
615                         }
616                         f = 1.0f / f;
617                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
618                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
619                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
620                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
621                 }
622         }
623         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
624 }
625
626 //=======================================================================================================================================================
627
628 static const char *builtinshaderstrings[] =
629 {
630 #include "shader_glsl.h"
631 0
632 };
633
634 const char *builtinhlslshaderstrings[] =
635 {
636 #include "shader_hlsl.h"
637 0
638 };
639
640 //=======================================================================================================================================================
641
642 typedef struct shaderpermutationinfo_s
643 {
644         const char *pretext;
645         const char *name;
646 }
647 shaderpermutationinfo_t;
648
649 typedef struct shadermodeinfo_s
650 {
651         const char *sourcebasename;
652         const char *extension;
653         const char **builtinshaderstrings;
654         const char *pretext;
655         const char *name;
656         char *filename;
657         char *builtinstring;
658         int builtincrc;
659 }
660 shadermodeinfo_t;
661
662 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
663 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
664 {
665         {"#define USEDIFFUSE\n", " diffuse"},
666         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
667         {"#define USEVIEWTINT\n", " viewtint"},
668         {"#define USECOLORMAPPING\n", " colormapping"},
669         {"#define USESATURATION\n", " saturation"},
670         {"#define USEFOGINSIDE\n", " foginside"},
671         {"#define USEFOGOUTSIDE\n", " fogoutside"},
672         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
673         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
674         {"#define USEGAMMARAMPS\n", " gammaramps"},
675         {"#define USECUBEFILTER\n", " cubefilter"},
676         {"#define USEGLOW\n", " glow"},
677         {"#define USEBLOOM\n", " bloom"},
678         {"#define USESPECULAR\n", " specular"},
679         {"#define USEPOSTPROCESSING\n", " postprocessing"},
680         {"#define USEREFLECTION\n", " reflection"},
681         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
682         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
683         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
684         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
685         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
686         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
687         {"#define USEALPHAKILL\n", " alphakill"},
688         {"#define USEREFLECTCUBE\n", " reflectcube"},
689         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
690         {"#define USEBOUNCEGRID\n", " bouncegrid"},
691         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
692         {"#define USETRIPPY\n", " trippy"},
693         {"#define USEDEPTHRGB\n", " depthrgb"},
694         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
695         {"#define USESKELETAL\n", " skeletal"},
696         {"#define USEOCCLUDE\n", " occlude"}
697 };
698
699 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
700 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
701 {
702         // SHADERLANGUAGE_GLSL
703         {
704                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
705                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
706                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
708                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
710                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
711                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
721         },
722         // SHADERLANGUAGE_HLSL
723         {
724                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
725                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
726                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
727                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
728                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
729                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
730                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
731                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
732                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
741         },
742 };
743
744 struct r_glsl_permutation_s;
745 typedef struct r_glsl_permutation_s
746 {
747         /// hash lookup data
748         struct r_glsl_permutation_s *hashnext;
749         unsigned int mode;
750         unsigned int permutation;
751
752         /// indicates if we have tried compiling this permutation already
753         qboolean compiled;
754         /// 0 if compilation failed
755         int program;
756         // texture units assigned to each detected uniform
757         int tex_Texture_First;
758         int tex_Texture_Second;
759         int tex_Texture_GammaRamps;
760         int tex_Texture_Normal;
761         int tex_Texture_Color;
762         int tex_Texture_Gloss;
763         int tex_Texture_Glow;
764         int tex_Texture_SecondaryNormal;
765         int tex_Texture_SecondaryColor;
766         int tex_Texture_SecondaryGloss;
767         int tex_Texture_SecondaryGlow;
768         int tex_Texture_Pants;
769         int tex_Texture_Shirt;
770         int tex_Texture_FogHeightTexture;
771         int tex_Texture_FogMask;
772         int tex_Texture_Lightmap;
773         int tex_Texture_Deluxemap;
774         int tex_Texture_Attenuation;
775         int tex_Texture_Cube;
776         int tex_Texture_Refraction;
777         int tex_Texture_Reflection;
778         int tex_Texture_ShadowMap2D;
779         int tex_Texture_CubeProjection;
780         int tex_Texture_ScreenNormalMap;
781         int tex_Texture_ScreenDiffuse;
782         int tex_Texture_ScreenSpecular;
783         int tex_Texture_ReflectMask;
784         int tex_Texture_ReflectCube;
785         int tex_Texture_BounceGrid;
786         /// locations of detected uniforms in program object, or -1 if not found
787         int loc_Texture_First;
788         int loc_Texture_Second;
789         int loc_Texture_GammaRamps;
790         int loc_Texture_Normal;
791         int loc_Texture_Color;
792         int loc_Texture_Gloss;
793         int loc_Texture_Glow;
794         int loc_Texture_SecondaryNormal;
795         int loc_Texture_SecondaryColor;
796         int loc_Texture_SecondaryGloss;
797         int loc_Texture_SecondaryGlow;
798         int loc_Texture_Pants;
799         int loc_Texture_Shirt;
800         int loc_Texture_FogHeightTexture;
801         int loc_Texture_FogMask;
802         int loc_Texture_Lightmap;
803         int loc_Texture_Deluxemap;
804         int loc_Texture_Attenuation;
805         int loc_Texture_Cube;
806         int loc_Texture_Refraction;
807         int loc_Texture_Reflection;
808         int loc_Texture_ShadowMap2D;
809         int loc_Texture_CubeProjection;
810         int loc_Texture_ScreenNormalMap;
811         int loc_Texture_ScreenDiffuse;
812         int loc_Texture_ScreenSpecular;
813         int loc_Texture_ReflectMask;
814         int loc_Texture_ReflectCube;
815         int loc_Texture_BounceGrid;
816         int loc_Alpha;
817         int loc_BloomBlur_Parameters;
818         int loc_ClientTime;
819         int loc_Color_Ambient;
820         int loc_Color_Diffuse;
821         int loc_Color_Specular;
822         int loc_Color_Glow;
823         int loc_Color_Pants;
824         int loc_Color_Shirt;
825         int loc_DeferredColor_Ambient;
826         int loc_DeferredColor_Diffuse;
827         int loc_DeferredColor_Specular;
828         int loc_DeferredMod_Diffuse;
829         int loc_DeferredMod_Specular;
830         int loc_DistortScaleRefractReflect;
831         int loc_EyePosition;
832         int loc_FogColor;
833         int loc_FogHeightFade;
834         int loc_FogPlane;
835         int loc_FogPlaneViewDist;
836         int loc_FogRangeRecip;
837         int loc_LightColor;
838         int loc_LightDir;
839         int loc_LightPosition;
840         int loc_OffsetMapping_ScaleSteps;
841         int loc_OffsetMapping_LodDistance;
842         int loc_OffsetMapping_Bias;
843         int loc_PixelSize;
844         int loc_ReflectColor;
845         int loc_ReflectFactor;
846         int loc_ReflectOffset;
847         int loc_RefractColor;
848         int loc_Saturation;
849         int loc_ScreenCenterRefractReflect;
850         int loc_ScreenScaleRefractReflect;
851         int loc_ScreenToDepth;
852         int loc_ShadowMap_Parameters;
853         int loc_ShadowMap_TextureScale;
854         int loc_SpecularPower;
855         int loc_Skeletal_Transform12;
856         int loc_UserVec1;
857         int loc_UserVec2;
858         int loc_UserVec3;
859         int loc_UserVec4;
860         int loc_ViewTintColor;
861         int loc_ViewToLight;
862         int loc_ModelToLight;
863         int loc_TexMatrix;
864         int loc_BackgroundTexMatrix;
865         int loc_ModelViewProjectionMatrix;
866         int loc_ModelViewMatrix;
867         int loc_PixelToScreenTexCoord;
868         int loc_ModelToReflectCube;
869         int loc_ShadowMapMatrix;
870         int loc_BloomColorSubtract;
871         int loc_NormalmapScrollBlend;
872         int loc_BounceGridMatrix;
873         int loc_BounceGridIntensity;
874         /// uniform block bindings
875         int ubibind_Skeletal_Transform12_UniformBlock;
876         /// uniform block indices
877         int ubiloc_Skeletal_Transform12_UniformBlock;
878 }
879 r_glsl_permutation_t;
880
881 #define SHADERPERMUTATION_HASHSIZE 256
882
883
884 // non-degradable "lightweight" shader parameters to keep the permutations simpler
885 // these can NOT degrade! only use for simple stuff
886 enum
887 {
888         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
889         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
890         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
891         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
892         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
893         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
894         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
895         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
896         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
897         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
898         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
899         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
900         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
901         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
902 };
903 #define SHADERSTATICPARMS_COUNT 14
904
905 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
906 static int shaderstaticparms_count = 0;
907
908 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
909 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
910
911 extern qboolean r_shadow_shadowmapsampler;
912 extern int r_shadow_shadowmappcf;
913 qboolean R_CompileShader_CheckStaticParms(void)
914 {
915         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
916         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
917         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
918
919         // detect all
920         if (r_glsl_saturation_redcompensate.integer)
921                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
922         if (r_glsl_vertextextureblend_usebothalphas.integer)
923                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
924         if (r_shadow_glossexact.integer)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
926         if (r_glsl_postprocess.integer)
927         {
928                 if (r_glsl_postprocess_uservec1_enable.integer)
929                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
930                 if (r_glsl_postprocess_uservec2_enable.integer)
931                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
932                 if (r_glsl_postprocess_uservec3_enable.integer)
933                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
934                 if (r_glsl_postprocess_uservec4_enable.integer)
935                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
936         }
937         if (r_fxaa.integer)
938                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
939         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
940                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
941
942         if (r_shadow_shadowmapsampler)
943                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
944         if (r_shadow_shadowmappcf > 1)
945                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
946         else if (r_shadow_shadowmappcf)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
948         if (r_celshading.integer)
949                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
950         if (r_celoutlines.integer)
951                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
952
953         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
954 }
955
956 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
957         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
958                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
959         else \
960                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
961 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
962 {
963         shaderstaticparms_count = 0;
964
965         // emit all
966         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
967         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
968         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
969         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
972         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
973         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
980 }
981
982 /// information about each possible shader permutation
983 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
984 /// currently selected permutation
985 r_glsl_permutation_t *r_glsl_permutation;
986 /// storage for permutations linked in the hash table
987 memexpandablearray_t r_glsl_permutationarray;
988
989 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
990 {
991         //unsigned int hashdepth = 0;
992         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
993         r_glsl_permutation_t *p;
994         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
995         {
996                 if (p->mode == mode && p->permutation == permutation)
997                 {
998                         //if (hashdepth > 10)
999                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1000                         return p;
1001                 }
1002                 //hashdepth++;
1003         }
1004         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1005         p->mode = mode;
1006         p->permutation = permutation;
1007         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1008         r_glsl_permutationhash[mode][hashindex] = p;
1009         //if (hashdepth > 10)
1010         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1011         return p;
1012 }
1013
1014 static char *R_ShaderStrCat(const char **strings)
1015 {
1016         char *string, *s;
1017         const char **p = strings;
1018         const char *t;
1019         size_t len = 0;
1020         for (p = strings;(t = *p);p++)
1021                 len += strlen(t);
1022         len++;
1023         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1024         len = 0;
1025         for (p = strings;(t = *p);p++)
1026         {
1027                 len = strlen(t);
1028                 memcpy(s, t, len);
1029                 s += len;
1030         }
1031         *s = 0;
1032         return string;
1033 }
1034
1035 static char *R_ShaderStrCat(const char **strings);
1036 static void R_InitShaderModeInfo(void)
1037 {
1038         int i, language;
1039         shadermodeinfo_t *modeinfo;
1040         // 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)
1041         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1042         {
1043                 for (i = 0; i < SHADERMODE_COUNT; i++)
1044                 {
1045                         char filename[MAX_QPATH];
1046                         modeinfo = &shadermodeinfo[language][i];
1047                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1048                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1049                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1050                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1051                 }
1052         }
1053 }
1054
1055 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1056 {
1057         char *shaderstring;
1058         // if the mode has no filename we have to return the builtin string
1059         if (builtinonly || !modeinfo->filename)
1060                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1061         // note that FS_LoadFile appends a 0 byte to make it a valid string
1062         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1063         if (shaderstring)
1064         {
1065                 if (printfromdisknotice)
1066                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1067                 return shaderstring;
1068         }
1069         // fall back to builtinstring
1070         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1071 }
1072
1073 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1074 {
1075         int i;
1076         int ubibind;
1077         int sampler;
1078         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1079         char *sourcestring;
1080         char permutationname[256];
1081         int vertstrings_count = 0;
1082         int geomstrings_count = 0;
1083         int fragstrings_count = 0;
1084         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1085         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1086         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1087
1088         if (p->compiled)
1089                 return;
1090         p->compiled = true;
1091         p->program = 0;
1092
1093         permutationname[0] = 0;
1094         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1095
1096         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1097
1098         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1099         if(vid.support.glshaderversion >= 140)
1100         {
1101                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1102                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1103                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1104                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1105                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1106                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1107         }
1108         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1109         else if(vid.support.glshaderversion >= 130)
1110         {
1111                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1112                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1113                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1114                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1115                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1116                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1117         }
1118         // if we can do #version 120, we should (this adds the invariant keyword)
1119         else if(vid.support.glshaderversion >= 120)
1120         {
1121                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1122                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1123                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1124                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1125                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1126                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1127         }
1128         // GLES also adds several things from GLSL120
1129         switch(vid.renderpath)
1130         {
1131         case RENDERPATH_GLES2:
1132                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1133                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1134                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1135                 break;
1136         default:
1137                 break;
1138         }
1139
1140         // the first pretext is which type of shader to compile as
1141         // (later these will all be bound together as a program object)
1142         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1143         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1144         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1145
1146         // the second pretext is the mode (for example a light source)
1147         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1148         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1149         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1150         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1151
1152         // now add all the permutation pretexts
1153         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1154         {
1155                 if (permutation & (1<<i))
1156                 {
1157                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1158                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1159                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1160                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1161                 }
1162                 else
1163                 {
1164                         // keep line numbers correct
1165                         vertstrings_list[vertstrings_count++] = "\n";
1166                         geomstrings_list[geomstrings_count++] = "\n";
1167                         fragstrings_list[fragstrings_count++] = "\n";
1168                 }
1169         }
1170
1171         // add static parms
1172         R_CompileShader_AddStaticParms(mode, permutation);
1173         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1174         vertstrings_count += shaderstaticparms_count;
1175         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1176         geomstrings_count += shaderstaticparms_count;
1177         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1178         fragstrings_count += shaderstaticparms_count;
1179
1180         // now append the shader text itself
1181         vertstrings_list[vertstrings_count++] = sourcestring;
1182         geomstrings_list[geomstrings_count++] = sourcestring;
1183         fragstrings_list[fragstrings_count++] = sourcestring;
1184
1185         // compile the shader program
1186         if (vertstrings_count + geomstrings_count + fragstrings_count)
1187                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1188         if (p->program)
1189         {
1190                 CHECKGLERROR
1191                 qglUseProgram(p->program);CHECKGLERROR
1192                 // look up all the uniform variable names we care about, so we don't
1193                 // have to look them up every time we set them
1194
1195 #if 0
1196                 // debugging aid
1197                 {
1198                         GLint activeuniformindex = 0;
1199                         GLint numactiveuniforms = 0;
1200                         char uniformname[128];
1201                         GLsizei uniformnamelength = 0;
1202                         GLint uniformsize = 0;
1203                         GLenum uniformtype = 0;
1204                         memset(uniformname, 0, sizeof(uniformname));
1205                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1206                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1207                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1208                         {
1209                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1210                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1211                         }
1212                 }
1213 #endif
1214
1215                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1216                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1217                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1218                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1219                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1220                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1221                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1222                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1223                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1224                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1225                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1226                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1227                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1228                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1229                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1230                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1231                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1232                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1233                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1234                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1235                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1236                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1237                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1238                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1239                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1240                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1241                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1242                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1243                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1244                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1245                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1246                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1247                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1248                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1249                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1250                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1251                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1252                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1253                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1254                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1255                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1256                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1257                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1258                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1259                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1260                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1261                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1262                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1263                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1264                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1265                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1266                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1267                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1268                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1269                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1270                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1271                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1272                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1273                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1274                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1275                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1276                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1277                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1278                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1279                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1280                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1281                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1282                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1283                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1284                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1285                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1286                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1287                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1288                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1289                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1290                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1291                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1292                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1293                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1294                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1295                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1296                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1297                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1298                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1299                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1300                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1301                 // initialize the samplers to refer to the texture units we use
1302                 p->tex_Texture_First = -1;
1303                 p->tex_Texture_Second = -1;
1304                 p->tex_Texture_GammaRamps = -1;
1305                 p->tex_Texture_Normal = -1;
1306                 p->tex_Texture_Color = -1;
1307                 p->tex_Texture_Gloss = -1;
1308                 p->tex_Texture_Glow = -1;
1309                 p->tex_Texture_SecondaryNormal = -1;
1310                 p->tex_Texture_SecondaryColor = -1;
1311                 p->tex_Texture_SecondaryGloss = -1;
1312                 p->tex_Texture_SecondaryGlow = -1;
1313                 p->tex_Texture_Pants = -1;
1314                 p->tex_Texture_Shirt = -1;
1315                 p->tex_Texture_FogHeightTexture = -1;
1316                 p->tex_Texture_FogMask = -1;
1317                 p->tex_Texture_Lightmap = -1;
1318                 p->tex_Texture_Deluxemap = -1;
1319                 p->tex_Texture_Attenuation = -1;
1320                 p->tex_Texture_Cube = -1;
1321                 p->tex_Texture_Refraction = -1;
1322                 p->tex_Texture_Reflection = -1;
1323                 p->tex_Texture_ShadowMap2D = -1;
1324                 p->tex_Texture_CubeProjection = -1;
1325                 p->tex_Texture_ScreenNormalMap = -1;
1326                 p->tex_Texture_ScreenDiffuse = -1;
1327                 p->tex_Texture_ScreenSpecular = -1;
1328                 p->tex_Texture_ReflectMask = -1;
1329                 p->tex_Texture_ReflectCube = -1;
1330                 p->tex_Texture_BounceGrid = -1;
1331                 // bind the texture samplers in use
1332                 sampler = 0;
1333                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1334                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1335                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1336                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1337                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1338                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1339                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1340                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1341                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1342                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1343                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1344                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1345                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1346                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1347                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1348                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1349                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1350                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1351                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1352                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1353                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1354                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1355                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1356                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1357                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1358                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1359                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1360                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1361                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1362                 // get the uniform block indices so we can bind them
1363 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1364                 if (vid.support.arb_uniform_buffer_object)
1365                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1366                 else
1367 #endif
1368                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1369                 // clear the uniform block bindings
1370                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1371                 // bind the uniform blocks in use
1372                 ubibind = 0;
1373 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1374                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1375 #endif
1376                 // we're done compiling and setting up the shader, at least until it is used
1377                 CHECKGLERROR
1378                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1379         }
1380         else
1381                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1382
1383         // free the strings
1384         if (sourcestring)
1385                 Mem_Free(sourcestring);
1386 }
1387
1388 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1389 {
1390         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1391         if (r_glsl_permutation != perm)
1392         {
1393                 r_glsl_permutation = perm;
1394                 if (!r_glsl_permutation->program)
1395                 {
1396                         if (!r_glsl_permutation->compiled)
1397                         {
1398                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1399                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1400                         }
1401                         if (!r_glsl_permutation->program)
1402                         {
1403                                 // remove features until we find a valid permutation
1404                                 int i;
1405                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1406                                 {
1407                                         // reduce i more quickly whenever it would not remove any bits
1408                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1409                                         if (!(permutation & j))
1410                                                 continue;
1411                                         permutation -= j;
1412                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1413                                         if (!r_glsl_permutation->compiled)
1414                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1415                                         if (r_glsl_permutation->program)
1416                                                 break;
1417                                 }
1418                                 if (i >= SHADERPERMUTATION_COUNT)
1419                                 {
1420                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1421                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1422                                         qglUseProgram(0);CHECKGLERROR
1423                                         return; // no bit left to clear, entire mode is broken
1424                                 }
1425                         }
1426                 }
1427                 CHECKGLERROR
1428                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1429         }
1430         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1431         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1432         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1433         CHECKGLERROR
1434 }
1435
1436 #ifdef SUPPORTD3D
1437
1438 #ifdef SUPPORTD3D
1439 #include <d3d9.h>
1440 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1441 extern D3DCAPS9 vid_d3d9caps;
1442 #endif
1443
1444 struct r_hlsl_permutation_s;
1445 typedef struct r_hlsl_permutation_s
1446 {
1447         /// hash lookup data
1448         struct r_hlsl_permutation_s *hashnext;
1449         unsigned int mode;
1450         unsigned int permutation;
1451
1452         /// indicates if we have tried compiling this permutation already
1453         qboolean compiled;
1454         /// NULL if compilation failed
1455         IDirect3DVertexShader9 *vertexshader;
1456         IDirect3DPixelShader9 *pixelshader;
1457 }
1458 r_hlsl_permutation_t;
1459
1460 typedef enum D3DVSREGISTER_e
1461 {
1462         D3DVSREGISTER_TexMatrix = 0, // float4x4
1463         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1464         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1465         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1466         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1467         D3DVSREGISTER_ModelToLight = 20, // float4x4
1468         D3DVSREGISTER_EyePosition = 24,
1469         D3DVSREGISTER_FogPlane = 25,
1470         D3DVSREGISTER_LightDir = 26,
1471         D3DVSREGISTER_LightPosition = 27,
1472 }
1473 D3DVSREGISTER_t;
1474
1475 typedef enum D3DPSREGISTER_e
1476 {
1477         D3DPSREGISTER_Alpha = 0,
1478         D3DPSREGISTER_BloomBlur_Parameters = 1,
1479         D3DPSREGISTER_ClientTime = 2,
1480         D3DPSREGISTER_Color_Ambient = 3,
1481         D3DPSREGISTER_Color_Diffuse = 4,
1482         D3DPSREGISTER_Color_Specular = 5,
1483         D3DPSREGISTER_Color_Glow = 6,
1484         D3DPSREGISTER_Color_Pants = 7,
1485         D3DPSREGISTER_Color_Shirt = 8,
1486         D3DPSREGISTER_DeferredColor_Ambient = 9,
1487         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1488         D3DPSREGISTER_DeferredColor_Specular = 11,
1489         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1490         D3DPSREGISTER_DeferredMod_Specular = 13,
1491         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1492         D3DPSREGISTER_EyePosition = 15, // unused
1493         D3DPSREGISTER_FogColor = 16,
1494         D3DPSREGISTER_FogHeightFade = 17,
1495         D3DPSREGISTER_FogPlane = 18,
1496         D3DPSREGISTER_FogPlaneViewDist = 19,
1497         D3DPSREGISTER_FogRangeRecip = 20,
1498         D3DPSREGISTER_LightColor = 21,
1499         D3DPSREGISTER_LightDir = 22, // unused
1500         D3DPSREGISTER_LightPosition = 23,
1501         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1502         D3DPSREGISTER_PixelSize = 25,
1503         D3DPSREGISTER_ReflectColor = 26,
1504         D3DPSREGISTER_ReflectFactor = 27,
1505         D3DPSREGISTER_ReflectOffset = 28,
1506         D3DPSREGISTER_RefractColor = 29,
1507         D3DPSREGISTER_Saturation = 30,
1508         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1509         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1510         D3DPSREGISTER_ScreenToDepth = 33,
1511         D3DPSREGISTER_ShadowMap_Parameters = 34,
1512         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1513         D3DPSREGISTER_SpecularPower = 36,
1514         D3DPSREGISTER_UserVec1 = 37,
1515         D3DPSREGISTER_UserVec2 = 38,
1516         D3DPSREGISTER_UserVec3 = 39,
1517         D3DPSREGISTER_UserVec4 = 40,
1518         D3DPSREGISTER_ViewTintColor = 41,
1519         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1520         D3DPSREGISTER_BloomColorSubtract = 43,
1521         D3DPSREGISTER_ViewToLight = 44, // float4x4
1522         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1523         D3DPSREGISTER_NormalmapScrollBlend = 52,
1524         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1525         D3DPSREGISTER_OffsetMapping_Bias = 54,
1526         // next at 54
1527 }
1528 D3DPSREGISTER_t;
1529
1530 /// information about each possible shader permutation
1531 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1532 /// currently selected permutation
1533 r_hlsl_permutation_t *r_hlsl_permutation;
1534 /// storage for permutations linked in the hash table
1535 memexpandablearray_t r_hlsl_permutationarray;
1536
1537 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1538 {
1539         //unsigned int hashdepth = 0;
1540         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1541         r_hlsl_permutation_t *p;
1542         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1543         {
1544                 if (p->mode == mode && p->permutation == permutation)
1545                 {
1546                         //if (hashdepth > 10)
1547                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1548                         return p;
1549                 }
1550                 //hashdepth++;
1551         }
1552         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1553         p->mode = mode;
1554         p->permutation = permutation;
1555         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1556         r_hlsl_permutationhash[mode][hashindex] = p;
1557         //if (hashdepth > 10)
1558         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1559         return p;
1560 }
1561
1562 #include <d3dx9.h>
1563 //#include <d3dx9shader.h>
1564 //#include <d3dx9mesh.h>
1565
1566 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1567 {
1568         DWORD *vsbin = NULL;
1569         DWORD *psbin = NULL;
1570         fs_offset_t vsbinsize;
1571         fs_offset_t psbinsize;
1572 //      IDirect3DVertexShader9 *vs = NULL;
1573 //      IDirect3DPixelShader9 *ps = NULL;
1574         ID3DXBuffer *vslog = NULL;
1575         ID3DXBuffer *vsbuffer = NULL;
1576         ID3DXConstantTable *vsconstanttable = NULL;
1577         ID3DXBuffer *pslog = NULL;
1578         ID3DXBuffer *psbuffer = NULL;
1579         ID3DXConstantTable *psconstanttable = NULL;
1580         int vsresult = 0;
1581         int psresult = 0;
1582         char temp[MAX_INPUTLINE];
1583         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1584         char vabuf[1024];
1585         qboolean debugshader = gl_paranoid.integer != 0;
1586         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1587         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1588         if (!debugshader)
1589         {
1590                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1591                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1592         }
1593         if ((!vsbin && vertstring) || (!psbin && fragstring))
1594         {
1595                 const char* dllnames_d3dx9 [] =
1596                 {
1597                         "d3dx9_43.dll",
1598                         "d3dx9_42.dll",
1599                         "d3dx9_41.dll",
1600                         "d3dx9_40.dll",
1601                         "d3dx9_39.dll",
1602                         "d3dx9_38.dll",
1603                         "d3dx9_37.dll",
1604                         "d3dx9_36.dll",
1605                         "d3dx9_35.dll",
1606                         "d3dx9_34.dll",
1607                         "d3dx9_33.dll",
1608                         "d3dx9_32.dll",
1609                         "d3dx9_31.dll",
1610                         "d3dx9_30.dll",
1611                         "d3dx9_29.dll",
1612                         "d3dx9_28.dll",
1613                         "d3dx9_27.dll",
1614                         "d3dx9_26.dll",
1615                         "d3dx9_25.dll",
1616                         "d3dx9_24.dll",
1617                         NULL
1618                 };
1619                 dllhandle_t d3dx9_dll = NULL;
1620                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1621                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1622                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1623                 dllfunction_t d3dx9_dllfuncs[] =
1624                 {
1625                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1626                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1627                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1628                         {NULL, NULL}
1629                 };
1630                 // 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...
1631 #ifndef ID3DXBuffer_GetBufferPointer
1632 #if !defined(__cplusplus) || defined(CINTERFACE)
1633 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1634 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1635 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1636 #else
1637 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1638 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1639 #define ID3DXBuffer_Release(p)            (p)->Release()
1640 #endif
1641 #endif
1642                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1643                 {
1644                         DWORD shaderflags = 0;
1645                         if (debugshader)
1646                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1647                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1648                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1649                         if (vertstring && vertstring[0])
1650                         {
1651                                 if (debugshader)
1652                                 {
1653                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1654                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1655                                 }
1656                                 else
1657                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1658                                 if (vsbuffer)
1659                                 {
1660                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1661                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1662                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1663                                         ID3DXBuffer_Release(vsbuffer);
1664                                 }
1665                                 if (vslog)
1666                                 {
1667                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1668                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1669                                         ID3DXBuffer_Release(vslog);
1670                                 }
1671                         }
1672                         if (fragstring && fragstring[0])
1673                         {
1674                                 if (debugshader)
1675                                 {
1676                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1677                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1678                                 }
1679                                 else
1680                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1681                                 if (psbuffer)
1682                                 {
1683                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1684                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1685                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1686                                         ID3DXBuffer_Release(psbuffer);
1687                                 }
1688                                 if (pslog)
1689                                 {
1690                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1691                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1692                                         ID3DXBuffer_Release(pslog);
1693                                 }
1694                         }
1695                         Sys_UnloadLibrary(&d3dx9_dll);
1696                 }
1697                 else
1698                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1699         }
1700         if (vsbin && psbin)
1701         {
1702                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1703                 if (FAILED(vsresult))
1704                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1705                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1706                 if (FAILED(psresult))
1707                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1708         }
1709         // free the shader data
1710         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1711         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1712 }
1713
1714 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1715 {
1716         int i;
1717         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1718         int vertstring_length = 0;
1719         int geomstring_length = 0;
1720         int fragstring_length = 0;
1721         char *t;
1722         char *sourcestring;
1723         char *vertstring, *geomstring, *fragstring;
1724         char permutationname[256];
1725         char cachename[256];
1726         int vertstrings_count = 0;
1727         int geomstrings_count = 0;
1728         int fragstrings_count = 0;
1729         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1730         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1731         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1732
1733         if (p->compiled)
1734                 return;
1735         p->compiled = true;
1736         p->vertexshader = NULL;
1737         p->pixelshader = NULL;
1738
1739         permutationname[0] = 0;
1740         cachename[0] = 0;
1741         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1742
1743         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1744         strlcat(cachename, "hlsl/", sizeof(cachename));
1745
1746         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1747         vertstrings_count = 0;
1748         geomstrings_count = 0;
1749         fragstrings_count = 0;
1750         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1751         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1752         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1753
1754         // the first pretext is which type of shader to compile as
1755         // (later these will all be bound together as a program object)
1756         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1757         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1758         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1759
1760         // the second pretext is the mode (for example a light source)
1761         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1762         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1763         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1764         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1765         strlcat(cachename, modeinfo->name, sizeof(cachename));
1766
1767         // now add all the permutation pretexts
1768         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1769         {
1770                 if (permutation & (1<<i))
1771                 {
1772                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1773                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1774                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1775                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1776                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1777                 }
1778                 else
1779                 {
1780                         // keep line numbers correct
1781                         vertstrings_list[vertstrings_count++] = "\n";
1782                         geomstrings_list[geomstrings_count++] = "\n";
1783                         fragstrings_list[fragstrings_count++] = "\n";
1784                 }
1785         }
1786
1787         // add static parms
1788         R_CompileShader_AddStaticParms(mode, permutation);
1789         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1790         vertstrings_count += shaderstaticparms_count;
1791         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1792         geomstrings_count += shaderstaticparms_count;
1793         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1794         fragstrings_count += shaderstaticparms_count;
1795
1796         // replace spaces in the cachename with _ characters
1797         for (i = 0;cachename[i];i++)
1798                 if (cachename[i] == ' ')
1799                         cachename[i] = '_';
1800
1801         // now append the shader text itself
1802         vertstrings_list[vertstrings_count++] = sourcestring;
1803         geomstrings_list[geomstrings_count++] = sourcestring;
1804         fragstrings_list[fragstrings_count++] = sourcestring;
1805
1806         vertstring_length = 0;
1807         for (i = 0;i < vertstrings_count;i++)
1808                 vertstring_length += (int)strlen(vertstrings_list[i]);
1809         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1810         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1811                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1812
1813         geomstring_length = 0;
1814         for (i = 0;i < geomstrings_count;i++)
1815                 geomstring_length += (int)strlen(geomstrings_list[i]);
1816         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1817         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1818                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1819
1820         fragstring_length = 0;
1821         for (i = 0;i < fragstrings_count;i++)
1822                 fragstring_length += (int)strlen(fragstrings_list[i]);
1823         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1824         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1825                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1826
1827         // try to load the cached shader, or generate one
1828         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1829
1830         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1831                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1832         else
1833                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1834
1835         // free the strings
1836         if (vertstring)
1837                 Mem_Free(vertstring);
1838         if (geomstring)
1839                 Mem_Free(geomstring);
1840         if (fragstring)
1841                 Mem_Free(fragstring);
1842         if (sourcestring)
1843                 Mem_Free(sourcestring);
1844 }
1845
1846 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1847 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1848 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);}
1849 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);}
1850 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);}
1851 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);}
1852
1853 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1854 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1855 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);}
1856 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);}
1857 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);}
1858 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);}
1859
1860 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1861 {
1862         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1863         if (r_hlsl_permutation != perm)
1864         {
1865                 r_hlsl_permutation = perm;
1866                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1867                 {
1868                         if (!r_hlsl_permutation->compiled)
1869                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1870                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1871                         {
1872                                 // remove features until we find a valid permutation
1873                                 int i;
1874                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1875                                 {
1876                                         // reduce i more quickly whenever it would not remove any bits
1877                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1878                                         if (!(permutation & j))
1879                                                 continue;
1880                                         permutation -= j;
1881                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1882                                         if (!r_hlsl_permutation->compiled)
1883                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1884                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1885                                                 break;
1886                                 }
1887                                 if (i >= SHADERPERMUTATION_COUNT)
1888                                 {
1889                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1890                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1891                                         return; // no bit left to clear, entire mode is broken
1892                                 }
1893                         }
1894                 }
1895                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1896                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1897         }
1898         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1899         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1900         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1901 }
1902 #endif
1903
1904 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1905 {
1906         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1907         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1908         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1909         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1910 }
1911
1912 void R_GLSL_Restart_f(void)
1913 {
1914         unsigned int i, limit;
1915         switch(vid.renderpath)
1916         {
1917         case RENDERPATH_D3D9:
1918 #ifdef SUPPORTD3D
1919                 {
1920                         r_hlsl_permutation_t *p;
1921                         r_hlsl_permutation = NULL;
1922                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1923                         for (i = 0;i < limit;i++)
1924                         {
1925                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1926                                 {
1927                                         if (p->vertexshader)
1928                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1929                                         if (p->pixelshader)
1930                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1931                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1932                                 }
1933                         }
1934                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1935                 }
1936 #endif
1937                 break;
1938         case RENDERPATH_D3D10:
1939                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1940                 break;
1941         case RENDERPATH_D3D11:
1942                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1943                 break;
1944         case RENDERPATH_GL20:
1945         case RENDERPATH_GLES2:
1946                 {
1947                         r_glsl_permutation_t *p;
1948                         r_glsl_permutation = NULL;
1949                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1950                         for (i = 0;i < limit;i++)
1951                         {
1952                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1953                                 {
1954                                         GL_Backend_FreeProgram(p->program);
1955                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1956                                 }
1957                         }
1958                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1959                 }
1960                 break;
1961         case RENDERPATH_GL11:
1962         case RENDERPATH_GL13:
1963         case RENDERPATH_GLES1:
1964                 break;
1965         case RENDERPATH_SOFT:
1966                 break;
1967         }
1968 }
1969
1970 static void R_GLSL_DumpShader_f(void)
1971 {
1972         int i, language, mode, dupe;
1973         char *text;
1974         shadermodeinfo_t *modeinfo;
1975         qfile_t *file;
1976
1977         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1978         {
1979                 modeinfo = shadermodeinfo[language];
1980                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1981                 {
1982                         // don't dump the same file multiple times (most or all shaders come from the same file)
1983                         for (dupe = mode - 1;dupe >= 0;dupe--)
1984                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1985                                         break;
1986                         if (dupe >= 0)
1987                                 continue;
1988                         text = modeinfo[mode].builtinstring;
1989                         if (!text)
1990                                 continue;
1991                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1992                         if (file)
1993                         {
1994                                 FS_Print(file, "/* The engine may define the following macros:\n");
1995                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1996                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1997                                         FS_Print(file, modeinfo[i].pretext);
1998                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1999                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2000                                 FS_Print(file, "*/\n");
2001                                 FS_Print(file, text);
2002                                 FS_Close(file);
2003                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2004                         }
2005                         else
2006                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2007                 }
2008         }
2009 }
2010
2011 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2012 {
2013         unsigned int permutation = 0;
2014         if (r_trippy.integer && !notrippy)
2015                 permutation |= SHADERPERMUTATION_TRIPPY;
2016         permutation |= SHADERPERMUTATION_VIEWTINT;
2017         if (first)
2018                 permutation |= SHADERPERMUTATION_DIFFUSE;
2019         if (second)
2020                 permutation |= SHADERPERMUTATION_SPECULAR;
2021         if (texturemode == GL_MODULATE)
2022                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2023         else if (texturemode == GL_ADD)
2024                 permutation |= SHADERPERMUTATION_GLOW;
2025         else if (texturemode == GL_DECAL)
2026                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2027         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2028                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2029         if (suppresstexalpha)
2030                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2031         if (!second)
2032                 texturemode = GL_MODULATE;
2033         if (vid.allowalphatocoverage)
2034                 GL_AlphaToCoverage(false);
2035         switch (vid.renderpath)
2036         {
2037         case RENDERPATH_D3D9:
2038 #ifdef SUPPORTD3D
2039                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2040                 R_Mesh_TexBind(GL20TU_FIRST , first );
2041                 R_Mesh_TexBind(GL20TU_SECOND, second);
2042                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2043                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2044 #endif
2045                 break;
2046         case RENDERPATH_D3D10:
2047                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2048                 break;
2049         case RENDERPATH_D3D11:
2050                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2051                 break;
2052         case RENDERPATH_GL20:
2053         case RENDERPATH_GLES2:
2054                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2055                 if (r_glsl_permutation->tex_Texture_First >= 0)
2056                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2057                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2058                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2059                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2060                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2061                 break;
2062         case RENDERPATH_GL13:
2063         case RENDERPATH_GLES1:
2064                 R_Mesh_TexBind(0, first );
2065                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2066                 R_Mesh_TexMatrix(0, NULL);
2067                 R_Mesh_TexBind(1, second);
2068                 if (second)
2069                 {
2070                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2071                         R_Mesh_TexMatrix(1, NULL);
2072                 }
2073                 break;
2074         case RENDERPATH_GL11:
2075                 R_Mesh_TexBind(0, first );
2076                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2077                 R_Mesh_TexMatrix(0, NULL);
2078                 break;
2079         case RENDERPATH_SOFT:
2080                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2081                 R_Mesh_TexBind(GL20TU_FIRST , first );
2082                 R_Mesh_TexBind(GL20TU_SECOND, second);
2083                 break;
2084         }
2085 }
2086
2087 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2088 {
2089         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2090 }
2091
2092 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2093 {
2094         unsigned int permutation = 0;
2095         if (r_trippy.integer && !notrippy)
2096                 permutation |= SHADERPERMUTATION_TRIPPY;
2097         if (depthrgb)
2098                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2099         if (skeletal)
2100                 permutation |= SHADERPERMUTATION_SKELETAL;
2101
2102         if (vid.allowalphatocoverage)
2103                 GL_AlphaToCoverage(false);
2104         switch (vid.renderpath)
2105         {
2106         case RENDERPATH_D3D9:
2107 #ifdef SUPPORTD3D
2108                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2109 #endif
2110                 break;
2111         case RENDERPATH_D3D10:
2112                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2113                 break;
2114         case RENDERPATH_D3D11:
2115                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2116                 break;
2117         case RENDERPATH_GL20:
2118         case RENDERPATH_GLES2:
2119                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2120 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2121                 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);
2122 #endif
2123                 break;
2124         case RENDERPATH_GL13:
2125         case RENDERPATH_GLES1:
2126                 R_Mesh_TexBind(0, 0);
2127                 R_Mesh_TexBind(1, 0);
2128                 break;
2129         case RENDERPATH_GL11:
2130                 R_Mesh_TexBind(0, 0);
2131                 break;
2132         case RENDERPATH_SOFT:
2133                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2134                 break;
2135         }
2136 }
2137
2138 extern qboolean r_shadow_usingdeferredprepass;
2139 extern rtexture_t *r_shadow_attenuationgradienttexture;
2140 extern rtexture_t *r_shadow_attenuation2dtexture;
2141 extern rtexture_t *r_shadow_attenuation3dtexture;
2142 extern qboolean r_shadow_usingshadowmap2d;
2143 extern qboolean r_shadow_usingshadowmaportho;
2144 extern float r_shadow_modelshadowmap_texturescale[4];
2145 extern float r_shadow_modelshadowmap_parameters[4];
2146 extern float r_shadow_lightshadowmap_texturescale[4];
2147 extern float r_shadow_lightshadowmap_parameters[4];
2148 extern qboolean r_shadow_shadowmapvsdct;
2149 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2150 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2151 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2152 extern matrix4x4_t r_shadow_shadowmapmatrix;
2153 extern int r_shadow_prepass_width;
2154 extern int r_shadow_prepass_height;
2155 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2156 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2157 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2158 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2159
2160 #define BLENDFUNC_ALLOWS_COLORMOD      1
2161 #define BLENDFUNC_ALLOWS_FOG           2
2162 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2163 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2164 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2165 static int R_BlendFuncFlags(int src, int dst)
2166 {
2167         int r = 0;
2168
2169         // a blendfunc allows colormod if:
2170         // a) it can never keep the destination pixel invariant, or
2171         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2172         // this is to prevent unintended side effects from colormod
2173
2174         // a blendfunc allows fog if:
2175         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2176         // this is to prevent unintended side effects from fog
2177
2178         // these checks are the output of fogeval.pl
2179
2180         r |= BLENDFUNC_ALLOWS_COLORMOD;
2181         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2182         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2183         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2184         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2185         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2186         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2187         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2188         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2189         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2190         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2191         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2192         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2193         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2194         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2195         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2196         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2197         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2198         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2199         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2200         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2201         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2202
2203         return r;
2204 }
2205
2206 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)
2207 {
2208         // select a permutation of the lighting shader appropriate to this
2209         // combination of texture, entity, light source, and fogging, only use the
2210         // minimum features necessary to avoid wasting rendering time in the
2211         // fragment shader on features that are not being used
2212         unsigned int permutation = 0;
2213         unsigned int mode = 0;
2214         int blendfuncflags;
2215         static float dummy_colormod[3] = {1, 1, 1};
2216         float *colormod = rsurface.colormod;
2217         float m16f[16];
2218         matrix4x4_t tempmatrix;
2219         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2220         if (r_trippy.integer && !notrippy)
2221                 permutation |= SHADERPERMUTATION_TRIPPY;
2222         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2223                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2224         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2225                 permutation |= SHADERPERMUTATION_OCCLUDE;
2226         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2227                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2228         if (rsurfacepass == RSURFPASS_BACKGROUND)
2229         {
2230                 // distorted background
2231                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2232                 {
2233                         mode = SHADERMODE_WATER;
2234                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2235                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2236                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2237                         {
2238                                 // this is the right thing to do for wateralpha
2239                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2240                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2241                         }
2242                         else
2243                         {
2244                                 // this is the right thing to do for entity alpha
2245                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2246                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2247                         }
2248                 }
2249                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2250                 {
2251                         mode = SHADERMODE_REFRACTION;
2252                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2253                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2254                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2255                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2256                 }
2257                 else
2258                 {
2259                         mode = SHADERMODE_GENERIC;
2260                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2261                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2262                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2263                 }
2264                 if (vid.allowalphatocoverage)
2265                         GL_AlphaToCoverage(false);
2266         }
2267         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2268         {
2269                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2270                 {
2271                         switch(rsurface.texture->offsetmapping)
2272                         {
2273                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2274                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2275                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2276                         case OFFSETMAPPING_OFF: break;
2277                         }
2278                 }
2279                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2280                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2281                 // normalmap (deferred prepass), may use alpha test on diffuse
2282                 mode = SHADERMODE_DEFERREDGEOMETRY;
2283                 GL_BlendFunc(GL_ONE, GL_ZERO);
2284                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2285                 if (vid.allowalphatocoverage)
2286                         GL_AlphaToCoverage(false);
2287         }
2288         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2289         {
2290                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2291                 {
2292                         switch(rsurface.texture->offsetmapping)
2293                         {
2294                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2295                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2297                         case OFFSETMAPPING_OFF: break;
2298                         }
2299                 }
2300                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2301                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2302                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2303                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2304                 // light source
2305                 mode = SHADERMODE_LIGHTSOURCE;
2306                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2307                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2308                 if (diffusescale > 0)
2309                         permutation |= SHADERPERMUTATION_DIFFUSE;
2310                 if (specularscale > 0)
2311                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2312                 if (r_refdef.fogenabled)
2313                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2314                 if (rsurface.texture->colormapping)
2315                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2316                 if (r_shadow_usingshadowmap2d)
2317                 {
2318                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2319                         if(r_shadow_shadowmapvsdct)
2320                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2321
2322                         if (r_shadow_shadowmap2ddepthbuffer)
2323                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2324                 }
2325                 if (rsurface.texture->reflectmasktexture)
2326                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2327                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2328                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2329                 if (vid.allowalphatocoverage)
2330                         GL_AlphaToCoverage(false);
2331         }
2332         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2333         {
2334                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2335                 {
2336                         switch(rsurface.texture->offsetmapping)
2337                         {
2338                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2339                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2340                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2341                         case OFFSETMAPPING_OFF: break;
2342                         }
2343                 }
2344                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2345                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2346                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2347                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2348                 // unshaded geometry (fullbright or ambient model lighting)
2349                 mode = SHADERMODE_FLATCOLOR;
2350                 ambientscale = diffusescale = specularscale = 0;
2351                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2352                         permutation |= SHADERPERMUTATION_GLOW;
2353                 if (r_refdef.fogenabled)
2354                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2355                 if (rsurface.texture->colormapping)
2356                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2357                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2358                 {
2359                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2360                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2361
2362                         if (r_shadow_shadowmap2ddepthbuffer)
2363                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2364                 }
2365                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2366                         permutation |= SHADERPERMUTATION_REFLECTION;
2367                 if (rsurface.texture->reflectmasktexture)
2368                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2369                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2370                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2371                 // when using alphatocoverage, we don't need alphakill
2372                 if (vid.allowalphatocoverage)
2373                 {
2374                         if (r_transparent_alphatocoverage.integer)
2375                         {
2376                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2377                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2378                         }
2379                         else
2380                                 GL_AlphaToCoverage(false);
2381                 }
2382         }
2383         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2384         {
2385                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2386                 {
2387                         switch(rsurface.texture->offsetmapping)
2388                         {
2389                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2390                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2391                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2392                         case OFFSETMAPPING_OFF: break;
2393                         }
2394                 }
2395                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2396                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2397                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2398                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2399                 // directional model lighting
2400                 mode = SHADERMODE_LIGHTDIRECTION;
2401                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2402                         permutation |= SHADERPERMUTATION_GLOW;
2403                 permutation |= SHADERPERMUTATION_DIFFUSE;
2404                 if (specularscale > 0)
2405                         permutation |= SHADERPERMUTATION_SPECULAR;
2406                 if (r_refdef.fogenabled)
2407                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2408                 if (rsurface.texture->colormapping)
2409                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2410                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2411                 {
2412                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2413                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2414
2415                         if (r_shadow_shadowmap2ddepthbuffer)
2416                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2417                 }
2418                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2419                         permutation |= SHADERPERMUTATION_REFLECTION;
2420                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2421                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2422                 if (rsurface.texture->reflectmasktexture)
2423                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2424                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2425                 {
2426                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2427                         if (r_shadow_bouncegrid_state.directional)
2428                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2429                 }
2430                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2431                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2432                 // when using alphatocoverage, we don't need alphakill
2433                 if (vid.allowalphatocoverage)
2434                 {
2435                         if (r_transparent_alphatocoverage.integer)
2436                         {
2437                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2438                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2439                         }
2440                         else
2441                                 GL_AlphaToCoverage(false);
2442                 }
2443         }
2444         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2445         {
2446                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2447                 {
2448                         switch(rsurface.texture->offsetmapping)
2449                         {
2450                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2451                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2452                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2453                         case OFFSETMAPPING_OFF: break;
2454                         }
2455                 }
2456                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2457                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2458                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2459                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2460                 // ambient model lighting
2461                 mode = SHADERMODE_LIGHTDIRECTION;
2462                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2463                         permutation |= SHADERPERMUTATION_GLOW;
2464                 if (r_refdef.fogenabled)
2465                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2466                 if (rsurface.texture->colormapping)
2467                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2468                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2469                 {
2470                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2471                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2472
2473                         if (r_shadow_shadowmap2ddepthbuffer)
2474                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2475                 }
2476                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2477                         permutation |= SHADERPERMUTATION_REFLECTION;
2478                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2479                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2480                 if (rsurface.texture->reflectmasktexture)
2481                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2482                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2483                 {
2484                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2485                         if (r_shadow_bouncegrid_state.directional)
2486                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2487                 }
2488                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2489                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2490                 // when using alphatocoverage, we don't need alphakill
2491                 if (vid.allowalphatocoverage)
2492                 {
2493                         if (r_transparent_alphatocoverage.integer)
2494                         {
2495                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2496                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2497                         }
2498                         else
2499                                 GL_AlphaToCoverage(false);
2500                 }
2501         }
2502         else
2503         {
2504                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2505                 {
2506                         switch(rsurface.texture->offsetmapping)
2507                         {
2508                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2509                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2510                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2511                         case OFFSETMAPPING_OFF: break;
2512                         }
2513                 }
2514                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2515                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2516                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2517                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2518                 // lightmapped wall
2519                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2520                         permutation |= SHADERPERMUTATION_GLOW;
2521                 if (r_refdef.fogenabled)
2522                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2523                 if (rsurface.texture->colormapping)
2524                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2525                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2526                 {
2527                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2528                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2529
2530                         if (r_shadow_shadowmap2ddepthbuffer)
2531                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2532                 }
2533                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2534                         permutation |= SHADERPERMUTATION_REFLECTION;
2535                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2536                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2537                 if (rsurface.texture->reflectmasktexture)
2538                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2539                 if (FAKELIGHT_ENABLED)
2540                 {
2541                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2542                         mode = SHADERMODE_FAKELIGHT;
2543                         permutation |= SHADERPERMUTATION_DIFFUSE;
2544                         if (specularscale > 0)
2545                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2546                 }
2547                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2548                 {
2549                         // deluxemapping (light direction texture)
2550                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2551                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2552                         else
2553                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2554                         permutation |= SHADERPERMUTATION_DIFFUSE;
2555                         if (specularscale > 0)
2556                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2557                 }
2558                 else if (r_glsl_deluxemapping.integer >= 2)
2559                 {
2560                         // fake deluxemapping (uniform light direction in tangentspace)
2561                         if (rsurface.uselightmaptexture)
2562                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2563                         else
2564                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2565                         permutation |= SHADERPERMUTATION_DIFFUSE;
2566                         if (specularscale > 0)
2567                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2568                 }
2569                 else if (rsurface.uselightmaptexture)
2570                 {
2571                         // ordinary lightmapping (q1bsp, q3bsp)
2572                         mode = SHADERMODE_LIGHTMAP;
2573                 }
2574                 else
2575                 {
2576                         // ordinary vertex coloring (q3bsp)
2577                         mode = SHADERMODE_VERTEXCOLOR;
2578                 }
2579                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2580                 {
2581                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2582                         if (r_shadow_bouncegrid_state.directional)
2583                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2584                 }
2585                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2586                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2587                 // when using alphatocoverage, we don't need alphakill
2588                 if (vid.allowalphatocoverage)
2589                 {
2590                         if (r_transparent_alphatocoverage.integer)
2591                         {
2592                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2593                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2594                         }
2595                         else
2596                                 GL_AlphaToCoverage(false);
2597                 }
2598         }
2599         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2600                 colormod = dummy_colormod;
2601         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2602                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2603         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2604                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2605         switch(vid.renderpath)
2606         {
2607         case RENDERPATH_D3D9:
2608 #ifdef SUPPORTD3D
2609                 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);
2610                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2611                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2612                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2613                 if (mode == SHADERMODE_LIGHTSOURCE)
2614                 {
2615                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2616                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2617                 }
2618                 else
2619                 {
2620                         if (mode == SHADERMODE_LIGHTDIRECTION)
2621                         {
2622                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2623                         }
2624                 }
2625                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2626                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2627                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2628                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2629                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2630
2631                 if (mode == SHADERMODE_LIGHTSOURCE)
2632                 {
2633                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2634                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2635                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2636                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2637                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2638
2639                         // additive passes are only darkened by fog, not tinted
2640                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2641                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2642                 }
2643                 else
2644                 {
2645                         if (mode == SHADERMODE_FLATCOLOR)
2646                         {
2647                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2648                         }
2649                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2650                         {
2651                                 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]);
2652                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2653                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2654                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2655                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2656                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2657                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2658                         }
2659                         else
2660                         {
2661                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2662                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2663                                 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);
2664                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2665                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2666                         }
2667                         // additive passes are only darkened by fog, not tinted
2668                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2669                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2670                         else
2671                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2672                         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);
2673                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2674                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2675                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2676                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2677                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2678                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2679                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2680                         if (mode == SHADERMODE_WATER)
2681                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2682                 }
2683                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2684                 {
2685                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2686                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2687                 }
2688                 else
2689                 {
2690                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2691                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2692                 }
2693                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2694                 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));
2695                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2696                 if (rsurface.texture->pantstexture)
2697                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2698                 else
2699                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2700                 if (rsurface.texture->shirttexture)
2701                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2702                 else
2703                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2704                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2705                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2706                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2707                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2708                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2709                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2710                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2711                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2712                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2713                         );
2714                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2715                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2716                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2717                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2718
2719                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2720                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2721                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2722                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2723                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2724                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2725                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2726                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2727                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2728                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2729                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2730                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2731                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2732                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2733                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2734                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2735                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2736                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2737                 {
2738                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2739                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2740                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2741                 }
2742                 else
2743                 {
2744                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2745                 }
2746 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2747                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2748                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2749                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2750                 {
2751                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2752                         if (rsurface.rtlight)
2753                         {
2754                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2755                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2756                         }
2757                 }
2758 #endif
2759                 break;
2760         case RENDERPATH_D3D10:
2761                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2762                 break;
2763         case RENDERPATH_D3D11:
2764                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2765                 break;
2766         case RENDERPATH_GL20:
2767         case RENDERPATH_GLES2:
2768                 if (!vid.useinterleavedarrays)
2769                 {
2770                         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);
2771                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2772                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2773                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2774                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2775                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2776                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2777                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2778                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2779                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2780                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2781                 }
2782                 else
2783                 {
2784                         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);
2785                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2786                 }
2787                 // this has to be after RSurf_PrepareVerticesForBatch
2788                 if (rsurface.batchskeletaltransform3x4buffer)
2789                         permutation |= SHADERPERMUTATION_SKELETAL;
2790                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2791 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2792                 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);
2793 #endif
2794                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2795                 if (mode == SHADERMODE_LIGHTSOURCE)
2796                 {
2797                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2798                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2799                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2800                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2801                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2802                         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);
2803         
2804                         // additive passes are only darkened by fog, not tinted
2805                         if (r_glsl_permutation->loc_FogColor >= 0)
2806                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2807                         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);
2808                 }
2809                 else
2810                 {
2811                         if (mode == SHADERMODE_FLATCOLOR)
2812                         {
2813                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2814                         }
2815                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2816                         {
2817                                 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]);
2818                                 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]);
2819                                 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);
2820                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2821                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2822                                 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]);
2823                                 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]);
2824                         }
2825                         else
2826                         {
2827                                 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]);
2828                                 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]);
2829                                 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);
2830                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2831                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2832                         }
2833                         // additive passes are only darkened by fog, not tinted
2834                         if (r_glsl_permutation->loc_FogColor >= 0)
2835                         {
2836                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2837                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2838                                 else
2839                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2840                         }
2841                         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);
2842                         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]);
2843                         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]);
2844                         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]);
2845                         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]);
2846                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2847                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2848                         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);
2849                         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]);
2850                 }
2851                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2852                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2853                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2854                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2855                 {
2856                         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]);
2857                         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]);
2858                 }
2859                 else
2860                 {
2861                         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]);
2862                         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]);
2863                 }
2864
2865                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2866                 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));
2867                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2868                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2869                 {
2870                         if (rsurface.texture->pantstexture)
2871                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2872                         else
2873                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2874                 }
2875                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2876                 {
2877                         if (rsurface.texture->shirttexture)
2878                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2879                         else
2880                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2881                 }
2882                 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]);
2883                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2884                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2885                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2886                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2887                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2888                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2889                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2890                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2891                         );
2892                 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);
2893                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2894                 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]);
2895                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2896                 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);}
2897                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2898
2899                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2900                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2901                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2902                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2903                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2904                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2905                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2906                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2907                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2908                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2909                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2910                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2911                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2912                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2913                 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);
2914                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2915                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2916                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2917                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2918                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2919                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2920                 {
2921                         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);
2922                         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);
2923                         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);
2924                 }
2925                 else
2926                 {
2927                         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);
2928                 }
2929                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2930                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2931                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2932                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2933                 {
2934                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2935                         if (rsurface.rtlight)
2936                         {
2937                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2938                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2939                         }
2940                 }
2941                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2942                 CHECKGLERROR
2943                 break;
2944         case RENDERPATH_GL11:
2945         case RENDERPATH_GL13:
2946         case RENDERPATH_GLES1:
2947                 break;
2948         case RENDERPATH_SOFT:
2949                 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);
2950                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2951                 R_SetupShader_SetPermutationSoft(mode, permutation);
2952                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2953                 if (mode == SHADERMODE_LIGHTSOURCE)
2954                 {
2955                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2956                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2957                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2958                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2959                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2960                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2961         
2962                         // additive passes are only darkened by fog, not tinted
2963                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2964                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2965                 }
2966                 else
2967                 {
2968                         if (mode == SHADERMODE_FLATCOLOR)
2969                         {
2970                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2971                         }
2972                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2973                         {
2974                                 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]);
2975                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2976                                 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);
2977                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2978                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2979                                 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]);
2980                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2981                         }
2982                         else
2983                         {
2984                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2985                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2986                                 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);
2987                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2988                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2989                         }
2990                         // additive passes are only darkened by fog, not tinted
2991                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2992                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2993                         else
2994                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2995                         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);
2996                         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]);
2997                         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]);
2998                         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]);
2999                         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]);
3000                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3001                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
3002                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3003                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
3004                 }
3005                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
3006                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
3007                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
3008                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
3009                 {
3010                         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]);
3011                         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]);
3012                 }
3013                 else
3014                 {
3015                         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]);
3016                         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]);
3017                 }
3018
3019                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3020                 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));
3021                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3022                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3023                 {
3024                         if (rsurface.texture->pantstexture)
3025                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3026                         else
3027                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3028                 }
3029                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3030                 {
3031                         if (rsurface.texture->shirttexture)
3032                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3033                         else
3034                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3035                 }
3036                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3037                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3038                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3039                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3040                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3041                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3042                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3043                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3044                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3045                         );
3046                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3047                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3048                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3049                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3050
3051                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3052                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3053                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3054                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3055                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3056                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3057                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3058                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3059                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3060                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3061                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3062                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3063                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3064                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3065                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3066                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3067                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3068                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3069                 {
3070                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3071                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3072                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3073                 }
3074                 else
3075                 {
3076                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3077                 }
3078 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3079                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3080                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3081                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3082                 {
3083                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3084                         if (rsurface.rtlight)
3085                         {
3086                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3087                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3088                         }
3089                 }
3090                 break;
3091         }
3092 }
3093
3094 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3095 {
3096         // select a permutation of the lighting shader appropriate to this
3097         // combination of texture, entity, light source, and fogging, only use the
3098         // minimum features necessary to avoid wasting rendering time in the
3099         // fragment shader on features that are not being used
3100         unsigned int permutation = 0;
3101         unsigned int mode = 0;
3102         const float *lightcolorbase = rtlight->currentcolor;
3103         float ambientscale = rtlight->ambientscale;
3104         float diffusescale = rtlight->diffusescale;
3105         float specularscale = rtlight->specularscale;
3106         // this is the location of the light in view space
3107         vec3_t viewlightorigin;
3108         // this transforms from view space (camera) to light space (cubemap)
3109         matrix4x4_t viewtolight;
3110         matrix4x4_t lighttoview;
3111         float viewtolight16f[16];
3112         // light source
3113         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3114         if (rtlight->currentcubemap != r_texture_whitecube)
3115                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3116         if (diffusescale > 0)
3117                 permutation |= SHADERPERMUTATION_DIFFUSE;
3118         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3119                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3120         if (r_shadow_usingshadowmap2d)
3121         {
3122                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3123                 if (r_shadow_shadowmapvsdct)
3124                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3125
3126                 if (r_shadow_shadowmap2ddepthbuffer)
3127                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3128         }
3129         if (vid.allowalphatocoverage)
3130                 GL_AlphaToCoverage(false);
3131         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3132         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3133         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3134         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3135         switch(vid.renderpath)
3136         {
3137         case RENDERPATH_D3D9:
3138 #ifdef SUPPORTD3D
3139                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3140                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3141                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3142                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3143                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3144                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3145                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3146                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3147                 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);
3148                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3149                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3150
3151                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3152                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3153                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3154                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3155                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3156 #endif
3157                 break;
3158         case RENDERPATH_D3D10:
3159                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3160                 break;
3161         case RENDERPATH_D3D11:
3162                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3163                 break;
3164         case RENDERPATH_GL20:
3165         case RENDERPATH_GLES2:
3166                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3167                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3168                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3169                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3170                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3171                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3172                 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]);
3173                 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]);
3174                 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);
3175                 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]);
3176                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3177
3178                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3179                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3180                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3181                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3182                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3183                 break;
3184         case RENDERPATH_GL11:
3185         case RENDERPATH_GL13:
3186         case RENDERPATH_GLES1:
3187                 break;
3188         case RENDERPATH_SOFT:
3189                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3190                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3191                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3192                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3193                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3194                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3195                 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]);
3196                 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]);
3197                 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);
3198                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3199                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3200
3201                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3202                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3203                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3204                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3205                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3206                 break;
3207         }
3208 }
3209
3210 #define SKINFRAME_HASH 1024
3211
3212 typedef struct
3213 {
3214         unsigned int loadsequence; // incremented each level change
3215         memexpandablearray_t array;
3216         skinframe_t *hash[SKINFRAME_HASH];
3217 }
3218 r_skinframe_t;
3219 r_skinframe_t r_skinframe;
3220
3221 void R_SkinFrame_PrepareForPurge(void)
3222 {
3223         r_skinframe.loadsequence++;
3224         // wrap it without hitting zero
3225         if (r_skinframe.loadsequence >= 200)
3226                 r_skinframe.loadsequence = 1;
3227 }
3228
3229 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3230 {
3231         if (!skinframe)
3232                 return;
3233         // mark the skinframe as used for the purging code
3234         skinframe->loadsequence = r_skinframe.loadsequence;
3235 }
3236
3237 void R_SkinFrame_Purge(void)
3238 {
3239         int i;
3240         skinframe_t *s;
3241         for (i = 0;i < SKINFRAME_HASH;i++)
3242         {
3243                 for (s = r_skinframe.hash[i];s;s = s->next)
3244                 {
3245                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3246                         {
3247                                 if (s->merged == s->base)
3248                                         s->merged = NULL;
3249                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3250                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3251                                 R_PurgeTexture(s->merged);s->merged = NULL;
3252                                 R_PurgeTexture(s->base  );s->base   = NULL;
3253                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3254                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3255                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3256                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3257                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3258                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3259                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3260                                 s->loadsequence = 0;
3261                         }
3262                 }
3263         }
3264 }
3265
3266 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3267         skinframe_t *item;
3268         char basename[MAX_QPATH];
3269
3270         Image_StripImageExtension(name, basename, sizeof(basename));
3271
3272         if( last == NULL ) {
3273                 int hashindex;
3274                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3275                 item = r_skinframe.hash[hashindex];
3276         } else {
3277                 item = last->next;
3278         }
3279
3280         // linearly search through the hash bucket
3281         for( ; item ; item = item->next ) {
3282                 if( !strcmp( item->basename, basename ) ) {
3283                         return item;
3284                 }
3285         }
3286         return NULL;
3287 }
3288
3289 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3290 {
3291         skinframe_t *item;
3292         int hashindex;
3293         char basename[MAX_QPATH];
3294
3295         Image_StripImageExtension(name, basename, sizeof(basename));
3296
3297         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3298         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3299                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3300                         break;
3301
3302         if (!item) {
3303                 rtexture_t *dyntexture;
3304                 // check whether its a dynamic texture
3305                 dyntexture = CL_GetDynTexture( basename );
3306                 if (!add && !dyntexture)
3307                         return NULL;
3308                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3309                 memset(item, 0, sizeof(*item));
3310                 strlcpy(item->basename, basename, sizeof(item->basename));
3311                 item->base = dyntexture; // either NULL or dyntexture handle
3312                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3313                 item->comparewidth = comparewidth;
3314                 item->compareheight = compareheight;
3315                 item->comparecrc = comparecrc;
3316                 item->next = r_skinframe.hash[hashindex];
3317                 r_skinframe.hash[hashindex] = item;
3318         }
3319         else if (textureflags & TEXF_FORCE_RELOAD)
3320         {
3321                 rtexture_t *dyntexture;
3322                 // check whether its a dynamic texture
3323                 dyntexture = CL_GetDynTexture( basename );
3324                 if (!add && !dyntexture)
3325                         return NULL;
3326                 if (item->merged == item->base)
3327                         item->merged = NULL;
3328                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3329                 R_PurgeTexture(item->stain );item->stain  = NULL;
3330                 R_PurgeTexture(item->merged);item->merged = NULL;
3331                 R_PurgeTexture(item->base  );item->base   = NULL;
3332                 R_PurgeTexture(item->pants );item->pants  = NULL;
3333                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3334                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3335                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3336                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3337                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3338         R_PurgeTexture(item->reflect);item->reflect = NULL;
3339                 item->loadsequence = 0;
3340         }
3341         else if( item->base == NULL )
3342         {
3343                 rtexture_t *dyntexture;
3344                 // check whether its a dynamic texture
3345                 // 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]
3346                 dyntexture = CL_GetDynTexture( basename );
3347                 item->base = dyntexture; // either NULL or dyntexture handle
3348         }
3349
3350         R_SkinFrame_MarkUsed(item);
3351         return item;
3352 }
3353
3354 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3355         { \
3356                 unsigned long long avgcolor[5], wsum; \
3357                 int pix, comp, w; \
3358                 avgcolor[0] = 0; \
3359                 avgcolor[1] = 0; \
3360                 avgcolor[2] = 0; \
3361                 avgcolor[3] = 0; \
3362                 avgcolor[4] = 0; \
3363                 wsum = 0; \
3364                 for(pix = 0; pix < cnt; ++pix) \
3365                 { \
3366                         w = 0; \
3367                         for(comp = 0; comp < 3; ++comp) \
3368                                 w += getpixel; \
3369                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3370                         { \
3371                                 ++wsum; \
3372                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3373                                 w = getpixel; \
3374                                 for(comp = 0; comp < 3; ++comp) \
3375                                         avgcolor[comp] += getpixel * w; \
3376                                 avgcolor[3] += w; \
3377                         } \
3378                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3379                         avgcolor[4] += getpixel; \
3380                 } \
3381                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3382                         avgcolor[3] = 1; \
3383                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3384                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3385                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3386                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3387         }
3388
3389 extern cvar_t gl_picmip;
3390 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3391 {
3392         int j;
3393         unsigned char *pixels;
3394         unsigned char *bumppixels;
3395         unsigned char *basepixels = NULL;
3396         int basepixels_width = 0;
3397         int basepixels_height = 0;
3398         skinframe_t *skinframe;
3399         rtexture_t *ddsbase = NULL;
3400         qboolean ddshasalpha = false;
3401         float ddsavgcolor[4];
3402         char basename[MAX_QPATH];
3403         int miplevel = R_PicmipForFlags(textureflags);
3404         int savemiplevel = miplevel;
3405         int mymiplevel;
3406         char vabuf[1024];
3407
3408         if (cls.state == ca_dedicated)
3409                 return NULL;
3410
3411         // return an existing skinframe if already loaded
3412         // if loading of the first image fails, don't make a new skinframe as it
3413         // would cause all future lookups of this to be missing
3414         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3415         if (skinframe && skinframe->base)
3416                 return skinframe;
3417
3418         Image_StripImageExtension(name, basename, sizeof(basename));
3419
3420         // check for DDS texture file first
3421         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3422         {
3423                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3424                 if (basepixels == NULL)
3425                         return NULL;
3426         }
3427
3428         // FIXME handle miplevel
3429
3430         if (developer_loading.integer)
3431                 Con_Printf("loading skin \"%s\"\n", name);
3432
3433         // we've got some pixels to store, so really allocate this new texture now
3434         if (!skinframe)
3435                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3436         textureflags &= ~TEXF_FORCE_RELOAD;
3437         skinframe->stain = NULL;
3438         skinframe->merged = NULL;
3439         skinframe->base = NULL;
3440         skinframe->pants = NULL;
3441         skinframe->shirt = NULL;
3442         skinframe->nmap = NULL;
3443         skinframe->gloss = NULL;
3444         skinframe->glow = NULL;
3445         skinframe->fog = NULL;
3446         skinframe->reflect = NULL;
3447         skinframe->hasalpha = false;
3448         // we could store the q2animname here too
3449
3450         if (ddsbase)
3451         {
3452                 skinframe->base = ddsbase;
3453                 skinframe->hasalpha = ddshasalpha;
3454                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3455                 if (r_loadfog && skinframe->hasalpha)
3456                         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);
3457                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3458         }
3459         else
3460         {
3461                 basepixels_width = image_width;
3462                 basepixels_height = image_height;
3463                 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);
3464                 if (textureflags & TEXF_ALPHA)
3465                 {
3466                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3467                         {
3468                                 if (basepixels[j] < 255)
3469                                 {
3470                                         skinframe->hasalpha = true;
3471                                         break;
3472                                 }
3473                         }
3474                         if (r_loadfog && skinframe->hasalpha)
3475                         {
3476                                 // has transparent pixels
3477                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3478                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3479                                 {
3480                                         pixels[j+0] = 255;
3481                                         pixels[j+1] = 255;
3482                                         pixels[j+2] = 255;
3483                                         pixels[j+3] = basepixels[j+3];
3484                                 }
3485                                 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);
3486                                 Mem_Free(pixels);
3487                         }
3488                 }
3489                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3490 #ifndef USE_GLES2
3491                 //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]);
3492                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3493                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3494                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3495                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3496 #endif
3497         }
3498
3499         if (r_loaddds)
3500         {
3501                 mymiplevel = savemiplevel;
3502                 if (r_loadnormalmap)
3503                         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);
3504                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3505                 if (r_loadgloss)
3506                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3507                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3508                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3509                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3510         }
3511
3512         // _norm is the name used by tenebrae and has been adopted as standard
3513         if (r_loadnormalmap && skinframe->nmap == NULL)
3514         {
3515                 mymiplevel = savemiplevel;
3516                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3517                 {
3518                         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);
3519                         Mem_Free(pixels);
3520                         pixels = NULL;
3521                 }
3522                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3523                 {
3524                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3525                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3526                         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);
3527                         Mem_Free(pixels);
3528                         Mem_Free(bumppixels);
3529                 }
3530                 else if (r_shadow_bumpscale_basetexture.value > 0)
3531                 {
3532                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3533                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3534                         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);
3535                         Mem_Free(pixels);
3536                 }
3537 #ifndef USE_GLES2
3538                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3539                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3540 #endif
3541         }
3542
3543         // _luma is supported only for tenebrae compatibility
3544         // _glow is the preferred name
3545         mymiplevel = savemiplevel;
3546         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))))
3547         {
3548                 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);
3549 #ifndef USE_GLES2
3550                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3551                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3552 #endif
3553                 Mem_Free(pixels);pixels = NULL;
3554         }
3555
3556         mymiplevel = savemiplevel;
3557         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3558         {
3559                 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);
3560 #ifndef USE_GLES2
3561                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3562                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3563 #endif
3564                 Mem_Free(pixels);
3565                 pixels = NULL;
3566         }
3567
3568         mymiplevel = savemiplevel;
3569         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3570         {
3571                 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);
3572 #ifndef USE_GLES2
3573                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3574                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3575 #endif
3576                 Mem_Free(pixels);
3577                 pixels = NULL;
3578         }
3579
3580         mymiplevel = savemiplevel;
3581         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3582         {
3583                 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);
3584 #ifndef USE_GLES2
3585                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3586                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3587 #endif
3588                 Mem_Free(pixels);
3589                 pixels = NULL;
3590         }
3591
3592         mymiplevel = savemiplevel;
3593         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3594         {
3595                 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);
3596 #ifndef USE_GLES2
3597                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3598                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3599 #endif
3600                 Mem_Free(pixels);
3601                 pixels = NULL;
3602         }
3603
3604         if (basepixels)
3605                 Mem_Free(basepixels);
3606
3607         return skinframe;
3608 }
3609
3610 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3611 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3612 {
3613         int i;
3614         skinframe_t *skinframe;
3615         char vabuf[1024];
3616
3617         if (cls.state == ca_dedicated)
3618                 return NULL;
3619
3620         // if already loaded just return it, otherwise make a new skinframe
3621         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3622         if (skinframe->base)
3623                 return skinframe;
3624         textureflags &= ~TEXF_FORCE_RELOAD;
3625
3626         skinframe->stain = NULL;
3627         skinframe->merged = NULL;
3628         skinframe->base = NULL;
3629         skinframe->pants = NULL;
3630         skinframe->shirt = NULL;
3631         skinframe->nmap = NULL;
3632         skinframe->gloss = NULL;
3633         skinframe->glow = NULL;
3634         skinframe->fog = NULL;
3635         skinframe->reflect = NULL;
3636         skinframe->hasalpha = false;
3637
3638         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3639         if (!skindata)
3640                 return NULL;
3641
3642         if (developer_loading.integer)
3643                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3644
3645         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3646         {
3647                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3648                 unsigned char *b = a + width * height * 4;
3649                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3650                 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);
3651                 Mem_Free(a);
3652         }
3653         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3654         if (textureflags & TEXF_ALPHA)
3655         {
3656                 for (i = 3;i < width * height * 4;i += 4)
3657                 {
3658                         if (skindata[i] < 255)
3659                         {
3660                                 skinframe->hasalpha = true;
3661                                 break;
3662                         }
3663                 }
3664                 if (r_loadfog && skinframe->hasalpha)
3665                 {
3666                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3667                         memcpy(fogpixels, skindata, width * height * 4);
3668                         for (i = 0;i < width * height * 4;i += 4)
3669                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3670                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3671                         Mem_Free(fogpixels);
3672                 }
3673         }
3674
3675         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3676         //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]);
3677
3678         return skinframe;
3679 }
3680
3681 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3682 {
3683         int i;
3684         int featuresmask;
3685         skinframe_t *skinframe;
3686
3687         if (cls.state == ca_dedicated)
3688                 return NULL;
3689
3690         // if already loaded just return it, otherwise make a new skinframe
3691         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3692         if (skinframe->base)
3693                 return skinframe;
3694         //textureflags &= ~TEXF_FORCE_RELOAD;
3695
3696         skinframe->stain = NULL;
3697         skinframe->merged = NULL;
3698         skinframe->base = NULL;
3699         skinframe->pants = NULL;
3700         skinframe->shirt = NULL;
3701         skinframe->nmap = NULL;
3702         skinframe->gloss = NULL;
3703         skinframe->glow = NULL;
3704         skinframe->fog = NULL;
3705         skinframe->reflect = NULL;
3706         skinframe->hasalpha = false;
3707
3708         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3709         if (!skindata)
3710                 return NULL;
3711
3712         if (developer_loading.integer)
3713                 Con_Printf("loading quake skin \"%s\"\n", name);
3714
3715         // 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)
3716         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3717         memcpy(skinframe->qpixels, skindata, width*height);
3718         skinframe->qwidth = width;
3719         skinframe->qheight = height;
3720
3721         featuresmask = 0;
3722         for (i = 0;i < width * height;i++)
3723                 featuresmask |= palette_featureflags[skindata[i]];
3724
3725         skinframe->hasalpha = false;
3726         // fence textures
3727         if (name[0] == '{')
3728                 skinframe->hasalpha = true;
3729         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3730         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3731         skinframe->qgeneratemerged = true;
3732         skinframe->qgeneratebase = skinframe->qhascolormapping;
3733         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3734
3735         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3736         //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]);
3737
3738         return skinframe;
3739 }
3740
3741 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3742 {
3743         int width;
3744         int height;
3745         unsigned char *skindata;
3746         char vabuf[1024];
3747
3748         if (!skinframe->qpixels)
3749                 return;
3750
3751         if (!skinframe->qhascolormapping)
3752                 colormapped = false;
3753
3754         if (colormapped)
3755         {
3756                 if (!skinframe->qgeneratebase)
3757                         return;
3758         }
3759         else
3760         {
3761                 if (!skinframe->qgeneratemerged)
3762                         return;
3763         }
3764
3765         width = skinframe->qwidth;
3766         height = skinframe->qheight;
3767         skindata = skinframe->qpixels;
3768
3769         if (skinframe->qgeneratenmap)
3770         {
3771                 unsigned char *a, *b;
3772                 skinframe->qgeneratenmap = false;
3773                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3774                 b = a + width * height * 4;
3775                 // use either a custom palette or the quake palette
3776                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3777                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3778                 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);
3779                 Mem_Free(a);
3780         }
3781
3782         if (skinframe->qgenerateglow)
3783         {
3784                 skinframe->qgenerateglow = false;
3785                 if (skinframe->hasalpha) // fence textures
3786                         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
3787                 else
3788                         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
3789         }
3790
3791         if (colormapped)
3792         {
3793                 skinframe->qgeneratebase = false;
3794                 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);
3795                 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);
3796                 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);
3797         }
3798         else
3799         {
3800                 skinframe->qgeneratemerged = false;
3801                 if (skinframe->hasalpha) // fence textures
3802                         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);
3803                 else
3804                         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);
3805         }
3806
3807         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3808         {
3809                 Mem_Free(skinframe->qpixels);
3810                 skinframe->qpixels = NULL;
3811         }
3812 }
3813
3814 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)
3815 {
3816         int i;
3817         skinframe_t *skinframe;
3818         char vabuf[1024];
3819
3820         if (cls.state == ca_dedicated)
3821                 return NULL;
3822
3823         // if already loaded just return it, otherwise make a new skinframe
3824         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3825         if (skinframe->base)
3826                 return skinframe;
3827         textureflags &= ~TEXF_FORCE_RELOAD;
3828
3829         skinframe->stain = NULL;
3830         skinframe->merged = NULL;
3831         skinframe->base = NULL;
3832         skinframe->pants = NULL;
3833         skinframe->shirt = NULL;
3834         skinframe->nmap = NULL;
3835         skinframe->gloss = NULL;
3836         skinframe->glow = NULL;
3837         skinframe->fog = NULL;
3838         skinframe->reflect = NULL;
3839         skinframe->hasalpha = false;
3840
3841         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3842         if (!skindata)
3843                 return NULL;
3844
3845         if (developer_loading.integer)
3846                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3847
3848         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3849         if (textureflags & TEXF_ALPHA)
3850         {
3851                 for (i = 0;i < width * height;i++)
3852                 {
3853                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3854                         {
3855                                 skinframe->hasalpha = true;
3856                                 break;
3857                         }
3858                 }
3859                 if (r_loadfog && skinframe->hasalpha)
3860                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3861         }
3862
3863         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3864         //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]);
3865
3866         return skinframe;
3867 }
3868
3869 skinframe_t *R_SkinFrame_LoadMissing(void)
3870 {
3871         skinframe_t *skinframe;
3872
3873         if (cls.state == ca_dedicated)
3874                 return NULL;
3875
3876         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3877         skinframe->stain = NULL;
3878         skinframe->merged = NULL;
3879         skinframe->base = NULL;
3880         skinframe->pants = NULL;
3881         skinframe->shirt = NULL;
3882         skinframe->nmap = NULL;
3883         skinframe->gloss = NULL;
3884         skinframe->glow = NULL;
3885         skinframe->fog = NULL;
3886         skinframe->reflect = NULL;
3887         skinframe->hasalpha = false;
3888
3889         skinframe->avgcolor[0] = rand() / RAND_MAX;
3890         skinframe->avgcolor[1] = rand() / RAND_MAX;
3891         skinframe->avgcolor[2] = rand() / RAND_MAX;
3892         skinframe->avgcolor[3] = 1;
3893
3894         return skinframe;
3895 }
3896
3897 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3898 typedef struct suffixinfo_s
3899 {
3900         const char *suffix;
3901         qboolean flipx, flipy, flipdiagonal;
3902 }
3903 suffixinfo_t;
3904 static suffixinfo_t suffix[3][6] =
3905 {
3906         {
3907                 {"px",   false, false, false},
3908                 {"nx",   false, false, false},
3909                 {"py",   false, false, false},
3910                 {"ny",   false, false, false},
3911                 {"pz",   false, false, false},
3912                 {"nz",   false, false, false}
3913         },
3914         {
3915                 {"posx", false, false, false},
3916                 {"negx", false, false, false},
3917                 {"posy", false, false, false},
3918                 {"negy", false, false, false},
3919                 {"posz", false, false, false},
3920                 {"negz", false, false, false}
3921         },
3922         {
3923                 {"rt",    true, false,  true},
3924                 {"lf",   false,  true,  true},
3925                 {"ft",    true,  true, false},
3926                 {"bk",   false, false, false},
3927                 {"up",    true, false,  true},
3928                 {"dn",    true, false,  true}
3929         }
3930 };
3931
3932 static int componentorder[4] = {0, 1, 2, 3};
3933
3934 static rtexture_t *R_LoadCubemap(const char *basename)
3935 {
3936         int i, j, cubemapsize;
3937         unsigned char *cubemappixels, *image_buffer;
3938         rtexture_t *cubemaptexture;
3939         char name[256];
3940         // must start 0 so the first loadimagepixels has no requested width/height
3941         cubemapsize = 0;
3942         cubemappixels = NULL;
3943         cubemaptexture = NULL;
3944         // keep trying different suffix groups (posx, px, rt) until one loads
3945         for (j = 0;j < 3 && !cubemappixels;j++)
3946         {
3947                 // load the 6 images in the suffix group
3948                 for (i = 0;i < 6;i++)
3949                 {
3950                         // generate an image name based on the base and and suffix
3951                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3952                         // load it
3953                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3954                         {
3955                                 // an image loaded, make sure width and height are equal
3956                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3957                                 {
3958                                         // if this is the first image to load successfully, allocate the cubemap memory
3959                                         if (!cubemappixels && image_width >= 1)
3960                                         {
3961                                                 cubemapsize = image_width;
3962                                                 // note this clears to black, so unavailable sides are black
3963                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3964                                         }
3965                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3966                                         if (cubemappixels)
3967                                                 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);
3968                                 }
3969                                 else
3970                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3971                                 // free the image
3972                                 Mem_Free(image_buffer);
3973                         }
3974                 }
3975         }
3976         // if a cubemap loaded, upload it
3977         if (cubemappixels)
3978         {
3979                 if (developer_loading.integer)
3980                         Con_Printf("loading cubemap \"%s\"\n", basename);
3981
3982                 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);
3983                 Mem_Free(cubemappixels);
3984         }
3985         else
3986         {
3987                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3988                 if (developer_loading.integer)
3989                 {
3990                         Con_Printf("(tried tried images ");
3991                         for (j = 0;j < 3;j++)
3992                                 for (i = 0;i < 6;i++)
3993                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3994                         Con_Print(" and was unable to find any of them).\n");
3995                 }
3996         }
3997         return cubemaptexture;
3998 }
3999
4000 rtexture_t *R_GetCubemap(const char *basename)
4001 {
4002         int i;
4003         for (i = 0;i < r_texture_numcubemaps;i++)
4004                 if (r_texture_cubemaps[i] != NULL)
4005                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
4006                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
4007         if (i >= MAX_CUBEMAPS || !r_main_mempool)
4008                 return r_texture_whitecube;
4009         r_texture_numcubemaps++;
4010         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
4011         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
4012         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
4013         return r_texture_cubemaps[i]->texture;
4014 }
4015
4016 static void R_Main_FreeViewCache(void)
4017 {
4018         if (r_refdef.viewcache.entityvisible)
4019                 Mem_Free(r_refdef.viewcache.entityvisible);
4020         if (r_refdef.viewcache.world_pvsbits)
4021                 Mem_Free(r_refdef.viewcache.world_pvsbits);
4022         if (r_refdef.viewcache.world_leafvisible)
4023                 Mem_Free(r_refdef.viewcache.world_leafvisible);
4024         if (r_refdef.viewcache.world_surfacevisible)
4025                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4026         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4027 }
4028
4029 static void R_Main_ResizeViewCache(void)
4030 {
4031         int numentities = r_refdef.scene.numentities;
4032         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4033         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4034         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4035         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4036         if (r_refdef.viewcache.maxentities < numentities)
4037         {
4038                 r_refdef.viewcache.maxentities = numentities;
4039                 if (r_refdef.viewcache.entityvisible)
4040                         Mem_Free(r_refdef.viewcache.entityvisible);
4041                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4042         }
4043         if (r_refdef.viewcache.world_numclusters != numclusters)
4044         {
4045                 r_refdef.viewcache.world_numclusters = numclusters;
4046                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4047                 if (r_refdef.viewcache.world_pvsbits)
4048                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4049                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4050         }
4051         if (r_refdef.viewcache.world_numleafs != numleafs)
4052         {
4053                 r_refdef.viewcache.world_numleafs = numleafs;
4054                 if (r_refdef.viewcache.world_leafvisible)
4055                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4056                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4057         }
4058         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4059         {
4060                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4061                 if (r_refdef.viewcache.world_surfacevisible)
4062                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4063                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4064         }
4065 }
4066
4067 extern rtexture_t *loadingscreentexture;
4068 static void gl_main_start(void)
4069 {
4070         loadingscreentexture = NULL;
4071         r_texture_blanknormalmap = NULL;
4072         r_texture_white = NULL;
4073         r_texture_grey128 = NULL;
4074         r_texture_black = NULL;
4075         r_texture_whitecube = NULL;
4076         r_texture_normalizationcube = NULL;
4077         r_texture_fogattenuation = NULL;
4078         r_texture_fogheighttexture = NULL;
4079         r_texture_gammaramps = NULL;
4080         r_texture_numcubemaps = 0;
4081         r_uniformbufferalignment = 32;
4082
4083         r_loaddds = r_texture_dds_load.integer != 0;
4084         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4085
4086         switch(vid.renderpath)
4087         {
4088         case RENDERPATH_GL20:
4089         case RENDERPATH_D3D9:
4090         case RENDERPATH_D3D10:
4091         case RENDERPATH_D3D11:
4092         case RENDERPATH_SOFT:
4093         case RENDERPATH_GLES2:
4094                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4095                 Cvar_SetValueQuick(&gl_combine, 1);
4096                 Cvar_SetValueQuick(&r_glsl, 1);
4097                 r_loadnormalmap = true;
4098                 r_loadgloss = true;
4099                 r_loadfog = false;
4100 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4101                 if (vid.support.arb_uniform_buffer_object)
4102                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4103 #endif
4104                         break;
4105         case RENDERPATH_GL13:
4106         case RENDERPATH_GLES1:
4107                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4108                 Cvar_SetValueQuick(&gl_combine, 1);
4109                 Cvar_SetValueQuick(&r_glsl, 0);
4110                 r_loadnormalmap = false;
4111                 r_loadgloss = false;
4112                 r_loadfog = true;
4113                 break;
4114         case RENDERPATH_GL11:
4115                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4116                 Cvar_SetValueQuick(&gl_combine, 0);
4117                 Cvar_SetValueQuick(&r_glsl, 0);
4118                 r_loadnormalmap = false;
4119                 r_loadgloss = false;
4120                 r_loadfog = true;
4121                 break;
4122         }
4123
4124         R_AnimCache_Free();
4125         R_FrameData_Reset();
4126         R_BufferData_Reset();
4127
4128         r_numqueries = 0;
4129         r_maxqueries = 0;
4130         memset(r_queries, 0, sizeof(r_queries));
4131
4132         r_qwskincache = NULL;
4133         r_qwskincache_size = 0;
4134
4135         // due to caching of texture_t references, the collision cache must be reset
4136         Collision_Cache_Reset(true);
4137
4138         // set up r_skinframe loading system for textures
4139         memset(&r_skinframe, 0, sizeof(r_skinframe));
4140         r_skinframe.loadsequence = 1;
4141         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4142
4143         r_main_texturepool = R_AllocTexturePool();
4144         R_BuildBlankTextures();
4145         R_BuildNoTexture();
4146         if (vid.support.arb_texture_cube_map)
4147         {
4148                 R_BuildWhiteCube();
4149                 R_BuildNormalizationCube();
4150         }
4151         r_texture_fogattenuation = NULL;
4152         r_texture_fogheighttexture = NULL;
4153         r_texture_gammaramps = NULL;
4154         //r_texture_fogintensity = NULL;
4155         memset(&r_fb, 0, sizeof(r_fb));
4156         r_glsl_permutation = NULL;
4157         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4158         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4159 #ifdef SUPPORTD3D
4160         r_hlsl_permutation = NULL;
4161         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4162         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4163 #endif
4164         memset(&r_svbsp, 0, sizeof (r_svbsp));
4165
4166         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4167         r_texture_numcubemaps = 0;
4168
4169         r_refdef.fogmasktable_density = 0;
4170
4171 #ifdef __ANDROID__
4172         // For Steelstorm Android
4173         // FIXME CACHE the program and reload
4174         // FIXME see possible combinations for SS:BR android
4175         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4176         R_SetupShader_SetPermutationGLSL(0, 12);
4177         R_SetupShader_SetPermutationGLSL(0, 13);
4178         R_SetupShader_SetPermutationGLSL(0, 8388621);
4179         R_SetupShader_SetPermutationGLSL(3, 0);
4180         R_SetupShader_SetPermutationGLSL(3, 2048);
4181         R_SetupShader_SetPermutationGLSL(5, 0);
4182         R_SetupShader_SetPermutationGLSL(5, 2);
4183         R_SetupShader_SetPermutationGLSL(5, 2048);
4184         R_SetupShader_SetPermutationGLSL(5, 8388608);
4185         R_SetupShader_SetPermutationGLSL(11, 1);
4186         R_SetupShader_SetPermutationGLSL(11, 2049);
4187         R_SetupShader_SetPermutationGLSL(11, 8193);
4188         R_SetupShader_SetPermutationGLSL(11, 10241);
4189         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4190 #endif
4191 }
4192
4193 static void gl_main_shutdown(void)
4194 {
4195         R_AnimCache_Free();
4196         R_FrameData_Reset();
4197         R_BufferData_Reset();
4198
4199         R_Main_FreeViewCache();
4200
4201         switch(vid.renderpath)
4202         {
4203         case RENDERPATH_GL11:
4204         case RENDERPATH_GL13:
4205         case RENDERPATH_GL20:
4206         case RENDERPATH_GLES1:
4207         case RENDERPATH_GLES2:
4208 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4209                 if (r_maxqueries)
4210                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4211 #endif
4212                 break;
4213         case RENDERPATH_D3D9:
4214                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4215                 break;
4216         case RENDERPATH_D3D10:
4217                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4218                 break;
4219         case RENDERPATH_D3D11:
4220                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4221                 break;
4222         case RENDERPATH_SOFT:
4223                 break;
4224         }
4225
4226         r_numqueries = 0;
4227         r_maxqueries = 0;
4228         memset(r_queries, 0, sizeof(r_queries));
4229
4230         r_qwskincache = NULL;
4231         r_qwskincache_size = 0;
4232
4233         // clear out the r_skinframe state
4234         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4235         memset(&r_skinframe, 0, sizeof(r_skinframe));
4236
4237         if (r_svbsp.nodes)
4238                 Mem_Free(r_svbsp.nodes);
4239         memset(&r_svbsp, 0, sizeof (r_svbsp));
4240         R_FreeTexturePool(&r_main_texturepool);
4241         loadingscreentexture = NULL;
4242         r_texture_blanknormalmap = NULL;
4243         r_texture_white = NULL;
4244         r_texture_grey128 = NULL;
4245         r_texture_black = NULL;
4246         r_texture_whitecube = NULL;
4247         r_texture_normalizationcube = NULL;
4248         r_texture_fogattenuation = NULL;
4249         r_texture_fogheighttexture = NULL;
4250         r_texture_gammaramps = NULL;
4251         r_texture_numcubemaps = 0;
4252         //r_texture_fogintensity = NULL;
4253         memset(&r_fb, 0, sizeof(r_fb));
4254         R_GLSL_Restart_f();
4255
4256         r_glsl_permutation = NULL;
4257         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4258         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4259 #ifdef SUPPORTD3D
4260         r_hlsl_permutation = NULL;
4261         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4262         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4263 #endif
4264 }
4265
4266 static void gl_main_newmap(void)
4267 {
4268         // FIXME: move this code to client
4269         char *entities, entname[MAX_QPATH];
4270         if (r_qwskincache)
4271                 Mem_Free(r_qwskincache);
4272         r_qwskincache = NULL;
4273         r_qwskincache_size = 0;
4274         if (cl.worldmodel)
4275         {
4276                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4277                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4278                 {
4279                         CL_ParseEntityLump(entities);
4280                         Mem_Free(entities);
4281                         return;
4282                 }
4283                 if (cl.worldmodel->brush.entities)
4284                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4285         }
4286         R_Main_FreeViewCache();
4287
4288         R_FrameData_Reset();
4289         R_BufferData_Reset();
4290 }
4291
4292 void GL_Main_Init(void)
4293 {
4294         int i;
4295         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4296         R_InitShaderModeInfo();
4297
4298         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4299         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4300         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4301         if (gamemode == GAME_NEHAHRA)
4302         {
4303                 Cvar_RegisterVariable (&gl_fogenable);
4304                 Cvar_RegisterVariable (&gl_fogdensity);
4305                 Cvar_RegisterVariable (&gl_fogred);
4306                 Cvar_RegisterVariable (&gl_foggreen);
4307                 Cvar_RegisterVariable (&gl_fogblue);
4308                 Cvar_RegisterVariable (&gl_fogstart);
4309                 Cvar_RegisterVariable (&gl_fogend);
4310                 Cvar_RegisterVariable (&gl_skyclip);
4311         }
4312         Cvar_RegisterVariable(&r_motionblur);
4313         Cvar_RegisterVariable(&r_damageblur);
4314         Cvar_RegisterVariable(&r_motionblur_averaging);
4315         Cvar_RegisterVariable(&r_motionblur_randomize);
4316         Cvar_RegisterVariable(&r_motionblur_minblur);
4317         Cvar_RegisterVariable(&r_motionblur_maxblur);
4318         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4319         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4320         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4321         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4322         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4323         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4324         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4325         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4326         Cvar_RegisterVariable(&r_equalize_entities_by);
4327         Cvar_RegisterVariable(&r_equalize_entities_to);
4328         Cvar_RegisterVariable(&r_depthfirst);
4329         Cvar_RegisterVariable(&r_useinfinitefarclip);
4330         Cvar_RegisterVariable(&r_farclip_base);
4331         Cvar_RegisterVariable(&r_farclip_world);
4332         Cvar_RegisterVariable(&r_nearclip);
4333         Cvar_RegisterVariable(&r_deformvertexes);
4334         Cvar_RegisterVariable(&r_transparent);
4335         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4336         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4337         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4338         Cvar_RegisterVariable(&r_showoverdraw);
4339         Cvar_RegisterVariable(&r_showbboxes);
4340         Cvar_RegisterVariable(&r_showsurfaces);
4341         Cvar_RegisterVariable(&r_showtris);
4342         Cvar_RegisterVariable(&r_shownormals);
4343         Cvar_RegisterVariable(&r_showlighting);
4344         Cvar_RegisterVariable(&r_showshadowvolumes);
4345         Cvar_RegisterVariable(&r_showcollisionbrushes);
4346         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4347         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4348         Cvar_RegisterVariable(&r_showdisabledepthtest);
4349         Cvar_RegisterVariable(&r_drawportals);
4350         Cvar_RegisterVariable(&r_drawentities);
4351         Cvar_RegisterVariable(&r_draw2d);
4352         Cvar_RegisterVariable(&r_drawworld);
4353         Cvar_RegisterVariable(&r_cullentities_trace);
4354         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4355         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4356         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4357         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4358         Cvar_RegisterVariable(&r_sortentities);
4359         Cvar_RegisterVariable(&r_drawviewmodel);
4360         Cvar_RegisterVariable(&r_drawexteriormodel);
4361         Cvar_RegisterVariable(&r_speeds);
4362         Cvar_RegisterVariable(&r_fullbrights);
4363         Cvar_RegisterVariable(&r_wateralpha);
4364         Cvar_RegisterVariable(&r_dynamic);
4365         Cvar_RegisterVariable(&r_fakelight);
4366         Cvar_RegisterVariable(&r_fakelight_intensity);
4367         Cvar_RegisterVariable(&r_fullbright);
4368         Cvar_RegisterVariable(&r_shadows);
4369         Cvar_RegisterVariable(&r_shadows_darken);
4370         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4371         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4372         Cvar_RegisterVariable(&r_shadows_throwdistance);
4373         Cvar_RegisterVariable(&r_shadows_throwdirection);
4374         Cvar_RegisterVariable(&r_shadows_focus);
4375         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4376         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4377         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4378         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4379         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4380         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4381         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4382         Cvar_RegisterVariable(&r_fog_exp2);
4383         Cvar_RegisterVariable(&r_fog_clear);
4384         Cvar_RegisterVariable(&r_drawfog);
4385         Cvar_RegisterVariable(&r_transparentdepthmasking);
4386         Cvar_RegisterVariable(&r_transparent_sortmindist);
4387         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4388         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4389         Cvar_RegisterVariable(&r_texture_dds_load);
4390         Cvar_RegisterVariable(&r_texture_dds_save);
4391         Cvar_RegisterVariable(&r_textureunits);
4392         Cvar_RegisterVariable(&gl_combine);
4393         Cvar_RegisterVariable(&r_usedepthtextures);
4394         Cvar_RegisterVariable(&r_viewfbo);
4395         Cvar_RegisterVariable(&r_viewscale);
4396         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4397         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4398         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4399         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4400         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4401         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4402         Cvar_RegisterVariable(&r_glsl);
4403         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4404         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4405         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4406         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4407         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4408         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4409         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4410         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4411         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4412         Cvar_RegisterVariable(&r_glsl_postprocess);
4413         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4414         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4415         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4416         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4417         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4418         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4419         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4420         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4421         Cvar_RegisterVariable(&r_celshading);
4422         Cvar_RegisterVariable(&r_celoutlines);
4423
4424         Cvar_RegisterVariable(&r_water);
4425         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4426         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4427         Cvar_RegisterVariable(&r_water_clippingplanebias);
4428         Cvar_RegisterVariable(&r_water_refractdistort);
4429         Cvar_RegisterVariable(&r_water_reflectdistort);
4430         Cvar_RegisterVariable(&r_water_scissormode);
4431         Cvar_RegisterVariable(&r_water_lowquality);
4432         Cvar_RegisterVariable(&r_water_hideplayer);
4433         Cvar_RegisterVariable(&r_water_fbo);
4434
4435         Cvar_RegisterVariable(&r_lerpsprites);
4436         Cvar_RegisterVariable(&r_lerpmodels);
4437         Cvar_RegisterVariable(&r_lerplightstyles);
4438         Cvar_RegisterVariable(&r_waterscroll);
4439         Cvar_RegisterVariable(&r_bloom);
4440         Cvar_RegisterVariable(&r_bloom_colorscale);
4441         Cvar_RegisterVariable(&r_bloom_brighten);
4442         Cvar_RegisterVariable(&r_bloom_blur);
4443         Cvar_RegisterVariable(&r_bloom_resolution);
4444         Cvar_RegisterVariable(&r_bloom_colorexponent);
4445         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4446         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4447         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4448         Cvar_RegisterVariable(&r_hdr_glowintensity);
4449         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4450         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4451         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4452         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4453         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4454         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4455         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4456         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4457         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4458         Cvar_RegisterVariable(&developer_texturelogging);
4459         Cvar_RegisterVariable(&gl_lightmaps);
4460         Cvar_RegisterVariable(&r_test);
4461         Cvar_RegisterVariable(&r_batch_multidraw);
4462         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4463         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4464         Cvar_RegisterVariable(&r_glsl_skeletal);
4465         Cvar_RegisterVariable(&r_glsl_saturation);
4466         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4467         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4468         Cvar_RegisterVariable(&r_framedatasize);
4469         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4470                 Cvar_RegisterVariable(&r_buffermegs[i]);
4471         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4472         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4473                 Cvar_SetValue("r_fullbrights", 0);
4474 #ifdef DP_MOBILETOUCH
4475         // GLES devices have terrible depth precision in general, so...
4476         Cvar_SetValueQuick(&r_nearclip, 4);
4477         Cvar_SetValueQuick(&r_farclip_base, 4096);
4478         Cvar_SetValueQuick(&r_farclip_world, 0);
4479         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4480 #endif
4481         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4482 }
4483
4484 void Render_Init(void)
4485 {
4486         gl_backend_init();
4487         R_Textures_Init();
4488         GL_Main_Init();
4489         Font_Init();
4490         GL_Draw_Init();
4491         R_Shadow_Init();
4492         R_Sky_Init();
4493         GL_Surf_Init();
4494         Sbar_Init();
4495         R_Particles_Init();
4496         R_Explosion_Init();
4497         R_LightningBeams_Init();
4498         Mod_RenderInit();
4499 }
4500
4501 /*
4502 ===============
4503 GL_Init
4504 ===============
4505 */
4506 #ifndef USE_GLES2
4507 extern char *ENGINE_EXTENSIONS;
4508 void GL_Init (void)
4509 {
4510         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4511         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4512         gl_version = (const char *)qglGetString(GL_VERSION);
4513         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4514
4515         if (!gl_extensions)
4516                 gl_extensions = "";
4517         if (!gl_platformextensions)
4518                 gl_platformextensions = "";
4519
4520         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4521         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4522         Con_Printf("GL_VERSION: %s\n", gl_version);
4523         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4524         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4525
4526         VID_CheckExtensions();
4527
4528         // LordHavoc: report supported extensions
4529 #ifdef CONFIG_MENU
4530         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4531 #else
4532         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4533 #endif
4534
4535         // clear to black (loading plaque will be seen over this)
4536         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4537 }
4538 #endif
4539
4540 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4541 {
4542         int i;
4543         mplane_t *p;
4544         if (r_trippy.integer)
4545                 return false;
4546         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4547         {
4548                 p = r_refdef.view.frustum + i;
4549                 switch(p->signbits)
4550                 {
4551                 default:
4552                 case 0:
4553                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4554                                 return true;
4555                         break;
4556                 case 1:
4557                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4558                                 return true;
4559                         break;
4560                 case 2:
4561                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4562                                 return true;
4563                         break;
4564                 case 3:
4565                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4566                                 return true;
4567                         break;
4568                 case 4:
4569                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4570                                 return true;
4571                         break;
4572                 case 5:
4573                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4574                                 return true;
4575                         break;
4576                 case 6:
4577                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4578                                 return true;
4579                         break;
4580                 case 7:
4581                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4582                                 return true;
4583                         break;
4584                 }
4585         }
4586         return false;
4587 }
4588
4589 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4590 {
4591         int i;
4592         const mplane_t *p;
4593         if (r_trippy.integer)
4594                 return false;
4595         for (i = 0;i < numplanes;i++)
4596         {
4597                 p = planes + i;
4598                 switch(p->signbits)
4599                 {
4600                 default:
4601                 case 0:
4602                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4603                                 return true;
4604                         break;
4605                 case 1:
4606                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4607                                 return true;
4608                         break;
4609                 case 2:
4610                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4611                                 return true;
4612                         break;
4613                 case 3:
4614                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4615                                 return true;
4616                         break;
4617                 case 4:
4618                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4619                                 return true;
4620                         break;
4621                 case 5:
4622                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4623                                 return true;
4624                         break;
4625                 case 6:
4626                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4627                                 return true;
4628                         break;
4629                 case 7:
4630                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4631                                 return true;
4632                         break;
4633                 }
4634         }
4635         return false;
4636 }
4637
4638 //==================================================================================
4639
4640 // LordHavoc: this stores temporary data used within the same frame
4641
4642 typedef struct r_framedata_mem_s
4643 {
4644         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4645         size_t size; // how much usable space
4646         size_t current; // how much space in use
4647         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4648         size_t wantedsize; // how much space was allocated
4649         unsigned char *data; // start of real data (16byte aligned)
4650 }
4651 r_framedata_mem_t;
4652
4653 static r_framedata_mem_t *r_framedata_mem;
4654
4655 void R_FrameData_Reset(void)
4656 {
4657         while (r_framedata_mem)
4658         {
4659                 r_framedata_mem_t *next = r_framedata_mem->purge;
4660                 Mem_Free(r_framedata_mem);
4661                 r_framedata_mem = next;
4662         }
4663 }
4664
4665 static void R_FrameData_Resize(qboolean mustgrow)
4666 {
4667         size_t wantedsize;
4668         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4669         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4670         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4671         {
4672                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4673                 newmem->wantedsize = wantedsize;
4674                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4675                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4676                 newmem->current = 0;
4677                 newmem->mark = 0;
4678                 newmem->purge = r_framedata_mem;
4679                 r_framedata_mem = newmem;
4680         }
4681 }
4682
4683 void R_FrameData_NewFrame(void)
4684 {
4685         R_FrameData_Resize(false);
4686         if (!r_framedata_mem)
4687                 return;
4688         // if we ran out of space on the last frame, free the old memory now
4689         while (r_framedata_mem->purge)
4690         {
4691                 // repeatedly remove the second item in the list, leaving only head
4692                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4693                 Mem_Free(r_framedata_mem->purge);
4694                 r_framedata_mem->purge = next;
4695         }
4696         // reset the current mem pointer
4697         r_framedata_mem->current = 0;
4698         r_framedata_mem->mark = 0;
4699 }
4700
4701 void *R_FrameData_Alloc(size_t size)
4702 {
4703         void *data;
4704         float newvalue;
4705
4706         // align to 16 byte boundary - the data pointer is already aligned, so we
4707         // only need to ensure the size of every allocation is also aligned
4708         size = (size + 15) & ~15;
4709
4710         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4711         {
4712                 // emergency - we ran out of space, allocate more memory
4713                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4714                 newvalue = r_framedatasize.value * 2.0f;
4715                 // 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
4716                 if (sizeof(size_t) >= 8)
4717                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4718                 else
4719                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4720                 // this might not be a growing it, but we'll allocate another buffer every time
4721                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4722                 R_FrameData_Resize(true);
4723         }
4724
4725         data = r_framedata_mem->data + r_framedata_mem->current;
4726         r_framedata_mem->current += size;
4727
4728         // count the usage for stats
4729         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4730         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4731
4732         return (void *)data;
4733 }
4734
4735 void *R_FrameData_Store(size_t size, void *data)
4736 {
4737         void *d = R_FrameData_Alloc(size);
4738         if (d && data)
4739                 memcpy(d, data, size);
4740         return d;
4741 }
4742
4743 void R_FrameData_SetMark(void)
4744 {
4745         if (!r_framedata_mem)
4746                 return;
4747         r_framedata_mem->mark = r_framedata_mem->current;
4748 }
4749
4750 void R_FrameData_ReturnToMark(void)
4751 {
4752         if (!r_framedata_mem)
4753                 return;
4754         r_framedata_mem->current = r_framedata_mem->mark;
4755 }
4756
4757 //==================================================================================
4758
4759 // avoid reusing the same buffer objects on consecutive frames
4760 #define R_BUFFERDATA_CYCLE 3
4761
4762 typedef struct r_bufferdata_buffer_s
4763 {
4764         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4765         size_t size; // how much usable space
4766         size_t current; // how much space in use
4767         r_meshbuffer_t *buffer; // the buffer itself
4768 }
4769 r_bufferdata_buffer_t;
4770
4771 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4772 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4773
4774 /// frees all dynamic buffers
4775 void R_BufferData_Reset(void)
4776 {
4777         int cycle, type;
4778         r_bufferdata_buffer_t **p, *mem;
4779         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4780         {
4781                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4782                 {
4783                         // free all buffers
4784                         p = &r_bufferdata_buffer[cycle][type];
4785                         while (*p)
4786                         {
4787                                 mem = *p;
4788                                 *p = (*p)->purge;
4789                                 if (mem->buffer)
4790                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4791                                 Mem_Free(mem);
4792                         }
4793                 }
4794         }
4795 }
4796
4797 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4798 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4799 {
4800         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4801         size_t size;
4802         float newvalue = r_buffermegs[type].value;
4803
4804         // increase the cvar if we have to (but only if we already have a mem)
4805         if (mustgrow && mem)
4806                 newvalue *= 2.0f;
4807         newvalue = bound(0.25f, newvalue, 256.0f);
4808         while (newvalue * 1024*1024 < minsize)
4809                 newvalue *= 2.0f;
4810
4811         // clamp the cvar to valid range
4812         newvalue = bound(0.25f, newvalue, 256.0f);
4813         if (r_buffermegs[type].value != newvalue)
4814                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4815
4816         // calculate size in bytes
4817         size = (size_t)(newvalue * 1024*1024);
4818         size = bound(131072, size, 256*1024*1024);
4819
4820         // allocate a new buffer if the size is different (purge old one later)
4821         // or if we were told we must grow the buffer
4822         if (!mem || mem->size != size || mustgrow)
4823         {
4824                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4825                 mem->size = size;
4826                 mem->current = 0;
4827                 if (type == R_BUFFERDATA_VERTEX)
4828                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4829                 else if (type == R_BUFFERDATA_INDEX16)
4830                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4831                 else if (type == R_BUFFERDATA_INDEX32)
4832                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4833                 else if (type == R_BUFFERDATA_UNIFORM)
4834                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4835                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4836                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4837         }
4838 }
4839
4840 void R_BufferData_NewFrame(void)
4841 {
4842         int type;
4843         r_bufferdata_buffer_t **p, *mem;
4844         // cycle to the next frame's buffers
4845         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4846         // if we ran out of space on the last time we used these buffers, free the old memory now
4847         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4848         {
4849                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4850                 {
4851                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4852                         // free all but the head buffer, this is how we recycle obsolete
4853                         // buffers after they are no longer in use
4854                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4855                         while (*p)
4856                         {
4857                                 mem = *p;
4858                                 *p = (*p)->purge;
4859                                 if (mem->buffer)
4860                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4861                                 Mem_Free(mem);
4862                         }
4863                         // reset the current offset
4864                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4865                 }
4866         }
4867 }
4868
4869 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4870 {
4871         r_bufferdata_buffer_t *mem;
4872         int offset = 0;
4873         int padsize;
4874
4875         *returnbufferoffset = 0;
4876
4877         // align size to a byte boundary appropriate for the buffer type, this
4878         // makes all allocations have aligned start offsets
4879         if (type == R_BUFFERDATA_UNIFORM)
4880                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4881         else
4882                 padsize = (datasize + 15) & ~15;
4883
4884         // if we ran out of space in this buffer we must allocate a new one
4885         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)
4886                 R_BufferData_Resize(type, true, padsize);
4887
4888         // if the resize did not give us enough memory, fail
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                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4891
4892         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4893         offset = (int)mem->current;
4894         mem->current += padsize;
4895
4896         // upload the data to the buffer at the chosen offset
4897         if (offset == 0)
4898                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4899         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4900
4901         // count the usage for stats
4902         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4903         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4904
4905         // return the buffer offset
4906         *returnbufferoffset = offset;
4907
4908         return mem->buffer;
4909 }
4910
4911 //==================================================================================
4912
4913 // LordHavoc: animcache originally written by Echon, rewritten since then
4914
4915 /**
4916  * Animation cache prevents re-generating mesh data for an animated model
4917  * multiple times in one frame for lighting, shadowing, reflections, etc.
4918  */
4919
4920 void R_AnimCache_Free(void)
4921 {
4922 }
4923
4924 void R_AnimCache_ClearCache(void)
4925 {
4926         int i;
4927         entity_render_t *ent;
4928
4929         for (i = 0;i < r_refdef.scene.numentities;i++)
4930         {
4931                 ent = r_refdef.scene.entities[i];
4932                 ent->animcache_vertex3f = NULL;
4933                 ent->animcache_vertex3f_vertexbuffer = NULL;
4934                 ent->animcache_vertex3f_bufferoffset = 0;
4935                 ent->animcache_normal3f = NULL;
4936                 ent->animcache_normal3f_vertexbuffer = NULL;
4937                 ent->animcache_normal3f_bufferoffset = 0;
4938                 ent->animcache_svector3f = NULL;
4939                 ent->animcache_svector3f_vertexbuffer = NULL;
4940                 ent->animcache_svector3f_bufferoffset = 0;
4941                 ent->animcache_tvector3f = NULL;
4942                 ent->animcache_tvector3f_vertexbuffer = NULL;
4943                 ent->animcache_tvector3f_bufferoffset = 0;
4944                 ent->animcache_vertexmesh = NULL;
4945                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4946                 ent->animcache_vertexmesh_bufferoffset = 0;
4947                 ent->animcache_skeletaltransform3x4 = NULL;
4948                 ent->animcache_skeletaltransform3x4buffer = NULL;
4949                 ent->animcache_skeletaltransform3x4offset = 0;
4950                 ent->animcache_skeletaltransform3x4size = 0;
4951         }
4952 }
4953
4954 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4955 {
4956         int i;
4957
4958         // check if we need the meshbuffers
4959         if (!vid.useinterleavedarrays)
4960                 return;
4961
4962         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4963                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4964         // TODO: upload vertexbuffer?
4965         if (ent->animcache_vertexmesh)
4966         {
4967                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4968                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4969                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4970                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4971                 for (i = 0;i < numvertices;i++)
4972                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4973                 if (ent->animcache_svector3f)
4974                         for (i = 0;i < numvertices;i++)
4975                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4976                 if (ent->animcache_tvector3f)
4977                         for (i = 0;i < numvertices;i++)
4978                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4979                 if (ent->animcache_normal3f)
4980                         for (i = 0;i < numvertices;i++)
4981                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4982         }
4983 }
4984
4985 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4986 {
4987         dp_model_t *model = ent->model;
4988         int numvertices;
4989
4990         // see if this ent is worth caching
4991         if (!model || !model->Draw || !model->AnimateVertices)
4992                 return false;
4993         // nothing to cache if it contains no animations and has no skeleton
4994         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4995                 return false;
4996         // see if it is already cached for gpuskeletal
4997         if (ent->animcache_skeletaltransform3x4)
4998                 return false;
4999         // see if it is already cached as a mesh
5000         if (ent->animcache_vertex3f)
5001         {
5002                 // check if we need to add normals or tangents
5003                 if (ent->animcache_normal3f)
5004                         wantnormals = false;
5005                 if (ent->animcache_svector3f)
5006                         wanttangents = false;
5007                 if (!wantnormals && !wanttangents)
5008                         return false;
5009         }
5010
5011         // check which kind of cache we need to generate
5012         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5013         {
5014                 // cache the skeleton so the vertex shader can use it
5015                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5016                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5017                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5018                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5019                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
5020                 // note: this can fail if the buffer is at the grow limit
5021                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5022                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5023         }
5024         else if (ent->animcache_vertex3f)
5025         {
5026                 // mesh was already cached but we may need to add normals/tangents
5027                 // (this only happens with multiple views, reflections, cameras, etc)
5028                 if (wantnormals || wanttangents)
5029                 {
5030                         numvertices = model->surfmesh.num_vertices;
5031                         if (wantnormals)
5032                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5033                         if (wanttangents)
5034                         {
5035                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5036                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5037                         }
5038                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5039                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5040                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5041                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5042                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5043                 }
5044         }
5045         else
5046         {
5047                 // generate mesh cache
5048                 numvertices = model->surfmesh.num_vertices;
5049                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5050                 if (wantnormals)
5051                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5052                 if (wanttangents)
5053                 {
5054                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5055                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5056                 }
5057                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5058                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5059                 if (wantnormals || wanttangents)
5060                 {
5061                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5062                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5063                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5064                 }
5065                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5066                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5067                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5068         }
5069         return true;
5070 }
5071
5072 void R_AnimCache_CacheVisibleEntities(void)
5073 {
5074         int i;
5075         qboolean wantnormals = true;
5076         qboolean wanttangents = !r_showsurfaces.integer;
5077
5078         switch(vid.renderpath)
5079         {
5080         case RENDERPATH_GL20:
5081         case RENDERPATH_D3D9:
5082         case RENDERPATH_D3D10:
5083         case RENDERPATH_D3D11:
5084         case RENDERPATH_GLES2:
5085                 break;
5086         case RENDERPATH_GL11:
5087         case RENDERPATH_GL13:
5088         case RENDERPATH_GLES1:
5089                 wanttangents = false;
5090                 break;
5091         case RENDERPATH_SOFT:
5092                 break;
5093         }
5094
5095         if (r_shownormals.integer)
5096                 wanttangents = wantnormals = true;
5097
5098         // TODO: thread this
5099         // NOTE: R_PrepareRTLights() also caches entities
5100
5101         for (i = 0;i < r_refdef.scene.numentities;i++)
5102                 if (r_refdef.viewcache.entityvisible[i])
5103                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5104 }
5105
5106 //==================================================================================
5107
5108 extern cvar_t r_overheadsprites_pushback;
5109
5110 static void R_View_UpdateEntityLighting (void)
5111 {
5112         int i;
5113         entity_render_t *ent;
5114         vec3_t tempdiffusenormal, avg;
5115         vec_t f, fa, fd, fdd;
5116         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5117
5118         for (i = 0;i < r_refdef.scene.numentities;i++)
5119         {
5120                 ent = r_refdef.scene.entities[i];
5121
5122                 // skip unseen models
5123                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5124                         continue;
5125
5126                 // skip bsp models
5127                 if (ent->model && ent->model == cl.worldmodel)
5128                 {
5129                         // TODO: use modellight for r_ambient settings on world?
5130                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5131                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5132                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5133                         continue;
5134                 }
5135                 
5136                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5137                 {
5138                         // aleady updated by CSQC
5139                         // TODO: force modellight on BSP models in this case?
5140                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5141                 }
5142                 else
5143                 {
5144                         // fetch the lighting from the worldmodel data
5145                         VectorClear(ent->modellight_ambient);
5146                         VectorClear(ent->modellight_diffuse);
5147                         VectorClear(tempdiffusenormal);
5148                         if (ent->flags & RENDER_LIGHT)
5149                         {
5150                                 vec3_t org;
5151                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5152
5153                                 // complete lightning for lit sprites
5154                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5155                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5156                                 {
5157                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5158                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5159                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5160                                 }
5161                                 else
5162                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5163
5164                                 if(ent->flags & RENDER_EQUALIZE)
5165                                 {
5166                                         // first fix up ambient lighting...
5167                                         if(r_equalize_entities_minambient.value > 0)
5168                                         {
5169                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5170                                                 if(fd > 0)
5171                                                 {
5172                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5173                                                         if(fa < r_equalize_entities_minambient.value * fd)
5174                                                         {
5175                                                                 // solve:
5176                                                                 //   fa'/fd' = minambient
5177                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5178                                                                 //   ...
5179                                                                 //   fa' = fd' * minambient
5180                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5181                                                                 //   ...
5182                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5183                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5184                                                                 //   ...
5185                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5186                                                                 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
5187                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5188                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5189                                                         }
5190                                                 }
5191                                         }
5192
5193                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5194                                         {
5195                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5196                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5197                                                 f = fa + 0.25 * fd;
5198                                                 if(f > 0)
5199                                                 {
5200                                                         // adjust brightness and saturation to target
5201                                                         avg[0] = avg[1] = avg[2] = fa / f;
5202                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5203                                                         avg[0] = avg[1] = avg[2] = fd / f;
5204                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5205                                                 }
5206                                         }
5207                                 }
5208                         }
5209                         else // highly rare
5210                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5211                 }
5212
5213                 // move the light direction into modelspace coordinates for lighting code
5214                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5215                 if(VectorLength2(ent->modellight_lightdir) == 0)
5216                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5217                 VectorNormalize(ent->modellight_lightdir);
5218         }
5219 }
5220
5221 #define MAX_LINEOFSIGHTTRACES 64
5222
5223 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5224 {
5225         int i;
5226         vec3_t boxmins, boxmaxs;
5227         vec3_t start;
5228         vec3_t end;
5229         dp_model_t *model = r_refdef.scene.worldmodel;
5230
5231         if (!model || !model->brush.TraceLineOfSight)
5232                 return true;
5233
5234         // expand the box a little
5235         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5236         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5237         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5238         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5239         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5240         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5241
5242         // return true if eye is inside enlarged box
5243         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5244                 return true;
5245
5246         // try center
5247         VectorCopy(eye, start);
5248         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5249         if (model->brush.TraceLineOfSight(model, start, end))
5250                 return true;
5251
5252         // try various random positions
5253         for (i = 0;i < numsamples;i++)
5254         {
5255                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5256                 if (model->brush.TraceLineOfSight(model, start, end))
5257                         return true;
5258         }
5259
5260         return false;
5261 }
5262
5263
5264 static void R_View_UpdateEntityVisible (void)
5265 {
5266         int i;
5267         int renderimask;
5268         int samples;
5269         entity_render_t *ent;
5270
5271         if (r_refdef.envmap || r_fb.water.hideplayer)
5272                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5273         else if (chase_active.integer || r_fb.water.renderingscene)
5274                 renderimask = RENDER_VIEWMODEL;
5275         else
5276                 renderimask = RENDER_EXTERIORMODEL;
5277         if (!r_drawviewmodel.integer)
5278                 renderimask |= RENDER_VIEWMODEL;
5279         if (!r_drawexteriormodel.integer)
5280                 renderimask |= RENDER_EXTERIORMODEL;
5281         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5282         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5283         {
5284                 // worldmodel can check visibility
5285                 for (i = 0;i < r_refdef.scene.numentities;i++)
5286                 {
5287                         ent = r_refdef.scene.entities[i];
5288                         if (!(ent->flags & renderimask))
5289                         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)))
5290                         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))
5291                                 r_refdef.viewcache.entityvisible[i] = true;
5292                 }
5293         }
5294         else
5295         {
5296                 // no worldmodel or it can't check visibility
5297                 for (i = 0;i < r_refdef.scene.numentities;i++)
5298                 {
5299                         ent = r_refdef.scene.entities[i];
5300                         if (!(ent->flags & renderimask))
5301                         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)))
5302                                 r_refdef.viewcache.entityvisible[i] = true;
5303                 }
5304         }
5305         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5306                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5307         {
5308                 for (i = 0;i < r_refdef.scene.numentities;i++)
5309                 {
5310                         if (!r_refdef.viewcache.entityvisible[i])
5311                                 continue;
5312                         ent = r_refdef.scene.entities[i];
5313                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5314                         {
5315                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5316                                 if (samples < 0)
5317                                         continue; // temp entities do pvs only
5318                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5319                                         ent->last_trace_visibility = realtime;
5320                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5321                                         r_refdef.viewcache.entityvisible[i] = 0;
5322                         }
5323                 }
5324         }
5325 }
5326
5327 /// only used if skyrendermasked, and normally returns false
5328 static int R_DrawBrushModelsSky (void)
5329 {
5330         int i, sky;
5331         entity_render_t *ent;
5332
5333         sky = false;
5334         for (i = 0;i < r_refdef.scene.numentities;i++)
5335         {
5336                 if (!r_refdef.viewcache.entityvisible[i])
5337                         continue;
5338                 ent = r_refdef.scene.entities[i];
5339                 if (!ent->model || !ent->model->DrawSky)
5340                         continue;
5341                 ent->model->DrawSky(ent);
5342                 sky = true;
5343         }
5344         return sky;
5345 }
5346
5347 static void R_DrawNoModel(entity_render_t *ent);
5348 static void R_DrawModels(void)
5349 {
5350         int i;
5351         entity_render_t *ent;
5352
5353         for (i = 0;i < r_refdef.scene.numentities;i++)
5354         {
5355                 if (!r_refdef.viewcache.entityvisible[i])
5356                         continue;
5357                 ent = r_refdef.scene.entities[i];
5358                 r_refdef.stats[r_stat_entities]++;
5359                 /*
5360                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5361                 {
5362                         vec3_t f, l, u, o;
5363                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5364                         Con_Printf("R_DrawModels\n");
5365                         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]);
5366                         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);
5367                         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);
5368                 }
5369                 */
5370                 if (ent->model && ent->model->Draw != NULL)
5371                         ent->model->Draw(ent);
5372                 else
5373                         R_DrawNoModel(ent);
5374         }
5375 }
5376
5377 static void R_DrawModelsDepth(void)
5378 {
5379         int i;
5380         entity_render_t *ent;
5381
5382         for (i = 0;i < r_refdef.scene.numentities;i++)
5383         {
5384                 if (!r_refdef.viewcache.entityvisible[i])
5385                         continue;
5386                 ent = r_refdef.scene.entities[i];
5387                 if (ent->model && ent->model->DrawDepth != NULL)
5388                         ent->model->DrawDepth(ent);
5389         }
5390 }
5391
5392 static void R_DrawModelsDebug(void)
5393 {
5394         int i;
5395         entity_render_t *ent;
5396
5397         for (i = 0;i < r_refdef.scene.numentities;i++)
5398         {
5399                 if (!r_refdef.viewcache.entityvisible[i])
5400                         continue;
5401                 ent = r_refdef.scene.entities[i];
5402                 if (ent->model && ent->model->DrawDebug != NULL)
5403                         ent->model->DrawDebug(ent);
5404         }
5405 }
5406
5407 static void R_DrawModelsAddWaterPlanes(void)
5408 {
5409         int i;
5410         entity_render_t *ent;
5411
5412         for (i = 0;i < r_refdef.scene.numentities;i++)
5413         {
5414                 if (!r_refdef.viewcache.entityvisible[i])
5415                         continue;
5416                 ent = r_refdef.scene.entities[i];
5417                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5418                         ent->model->DrawAddWaterPlanes(ent);
5419         }
5420 }
5421
5422 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}};
5423
5424 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5425 {
5426         if (r_hdr_irisadaptation.integer)
5427         {
5428                 vec3_t p;
5429                 vec3_t ambient;
5430                 vec3_t diffuse;
5431                 vec3_t diffusenormal;
5432                 vec3_t forward;
5433                 vec_t brightness = 0.0f;
5434                 vec_t goal;
5435                 vec_t current;
5436                 vec_t d;
5437                 int c;
5438                 VectorCopy(r_refdef.view.forward, forward);
5439                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5440                 {
5441                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5442                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5443                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5444                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5445                         d = DotProduct(forward, diffusenormal);
5446                         brightness += VectorLength(ambient);
5447                         if (d > 0)
5448                                 brightness += d * VectorLength(diffuse);
5449                 }
5450                 brightness *= 1.0f / c;
5451                 brightness += 0.00001f; // make sure it's never zero
5452                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5453                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5454                 current = r_hdr_irisadaptation_value.value;
5455                 if (current < goal)
5456                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5457                 else if (current > goal)
5458                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5459                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5460                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5461         }
5462         else if (r_hdr_irisadaptation_value.value != 1.0f)
5463                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5464 }
5465
5466 static void R_View_SetFrustum(const int *scissor)
5467 {
5468         int i;
5469         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5470         vec3_t forward, left, up, origin, v;
5471
5472         if(scissor)
5473         {
5474                 // flipped x coordinates (because x points left here)
5475                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5476                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5477
5478                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5479                 switch(vid.renderpath)
5480                 {
5481                         case RENDERPATH_D3D9:
5482                         case RENDERPATH_D3D10:
5483                         case RENDERPATH_D3D11:
5484                                 // non-flipped y coordinates
5485                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5486                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5487                                 break;
5488                         case RENDERPATH_SOFT:
5489                         case RENDERPATH_GL11:
5490                         case RENDERPATH_GL13:
5491                         case RENDERPATH_GL20:
5492                         case RENDERPATH_GLES1:
5493                         case RENDERPATH_GLES2:
5494                                 // non-flipped y coordinates
5495                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5496                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5497                                 break;
5498                 }
5499         }
5500
5501         // we can't trust r_refdef.view.forward and friends in reflected scenes
5502         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5503
5504 #if 0
5505         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5506         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5507         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5508         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5509         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5510         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5511         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5512         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5513         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5514         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5515         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5516         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5517 #endif
5518
5519 #if 0
5520         zNear = r_refdef.nearclip;
5521         nudge = 1.0 - 1.0 / (1<<23);
5522         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5523         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5524         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5525         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5526         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5527         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5528         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5529         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5530 #endif
5531
5532
5533
5534 #if 0
5535         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5536         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5537         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5538         r_refdef.view.frustum[0].dist = m[15] - m[12];
5539
5540         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5541         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5542         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5543         r_refdef.view.frustum[1].dist = m[15] + m[12];
5544
5545         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5546         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5547         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5548         r_refdef.view.frustum[2].dist = m[15] - m[13];
5549
5550         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5551         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5552         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5553         r_refdef.view.frustum[3].dist = m[15] + m[13];
5554
5555         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5556         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5557         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5558         r_refdef.view.frustum[4].dist = m[15] - m[14];
5559
5560         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5561         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5562         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5563         r_refdef.view.frustum[5].dist = m[15] + m[14];
5564 #endif
5565
5566         if (r_refdef.view.useperspective)
5567         {
5568                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5569                 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]);
5570                 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]);
5571                 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]);
5572                 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]);
5573
5574                 // then the normals from the corners relative to origin
5575                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5576                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5577                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5578                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5579
5580                 // in a NORMAL view, forward cross left == up
5581                 // in a REFLECTED view, forward cross left == down
5582                 // so our cross products above need to be adjusted for a left handed coordinate system
5583                 CrossProduct(forward, left, v);
5584                 if(DotProduct(v, up) < 0)
5585                 {
5586                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5587                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5588                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5589                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5590                 }
5591
5592                 // Leaving those out was a mistake, those were in the old code, and they
5593                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5594                 // I couldn't reproduce it after adding those normalizations. --blub
5595                 VectorNormalize(r_refdef.view.frustum[0].normal);
5596                 VectorNormalize(r_refdef.view.frustum[1].normal);
5597                 VectorNormalize(r_refdef.view.frustum[2].normal);
5598                 VectorNormalize(r_refdef.view.frustum[3].normal);
5599
5600                 // make the corners absolute
5601                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5602                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5603                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5604                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5605
5606                 // one more normal
5607                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5608
5609                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5610                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5611                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5612                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5613                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5614         }
5615         else
5616         {
5617                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5618                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5619                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5620                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5621                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5622                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5623                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5624                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5625                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5626                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5627         }
5628         r_refdef.view.numfrustumplanes = 5;
5629
5630         if (r_refdef.view.useclipplane)
5631         {
5632                 r_refdef.view.numfrustumplanes = 6;
5633                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5634         }
5635
5636         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5637                 PlaneClassify(r_refdef.view.frustum + i);
5638
5639         // LordHavoc: note to all quake engine coders, Quake had a special case
5640         // for 90 degrees which assumed a square view (wrong), so I removed it,
5641         // Quake2 has it disabled as well.
5642
5643         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5644         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5645         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5646         //PlaneClassify(&frustum[0]);
5647
5648         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5649         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5650         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5651         //PlaneClassify(&frustum[1]);
5652
5653         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5654         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5655         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5656         //PlaneClassify(&frustum[2]);
5657
5658         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5659         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5660         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5661         //PlaneClassify(&frustum[3]);
5662
5663         // nearclip plane
5664         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5665         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5666         //PlaneClassify(&frustum[4]);
5667 }
5668
5669 static void R_View_UpdateWithScissor(const int *myscissor)
5670 {
5671         R_Main_ResizeViewCache();
5672         R_View_SetFrustum(myscissor);
5673         R_View_WorldVisibility(r_refdef.view.useclipplane);
5674         R_View_UpdateEntityVisible();
5675         R_View_UpdateEntityLighting();
5676 }
5677
5678 static void R_View_Update(void)
5679 {
5680         R_Main_ResizeViewCache();
5681         R_View_SetFrustum(NULL);
5682         R_View_WorldVisibility(r_refdef.view.useclipplane);
5683         R_View_UpdateEntityVisible();
5684         R_View_UpdateEntityLighting();
5685 }
5686
5687 float viewscalefpsadjusted = 1.0f;
5688
5689 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5690 {
5691         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5692         scale = bound(0.03125f, scale, 1.0f);
5693         *outwidth = (int)ceil(width * scale);
5694         *outheight = (int)ceil(height * scale);
5695 }
5696
5697 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5698 {
5699         const float *customclipplane = NULL;
5700         float plane[4];
5701         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5702         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5703         {
5704                 // LordHavoc: couldn't figure out how to make this approach the
5705                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5706                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5707                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5708                         dist = r_refdef.view.clipplane.dist;
5709                 plane[0] = r_refdef.view.clipplane.normal[0];
5710                 plane[1] = r_refdef.view.clipplane.normal[1];
5711                 plane[2] = r_refdef.view.clipplane.normal[2];
5712                 plane[3] = -dist;
5713                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5714         }
5715
5716         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5717         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5718
5719         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5720         if (!r_refdef.view.useperspective)
5721                 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);
5722         else if (vid.stencil && r_useinfinitefarclip.integer)
5723                 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);
5724         else
5725                 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);
5726         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5727         R_SetViewport(&r_refdef.view.viewport);
5728         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5729         {
5730                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5731                 float screenplane[4];
5732                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5733                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5734                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5735                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5736                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5737         }
5738 }
5739
5740 void R_EntityMatrix(const matrix4x4_t *matrix)
5741 {
5742         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5743         {
5744                 gl_modelmatrixchanged = false;
5745                 gl_modelmatrix = *matrix;
5746                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5747                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5748                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5749                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5750                 CHECKGLERROR
5751                 switch(vid.renderpath)
5752                 {
5753                 case RENDERPATH_D3D9:
5754 #ifdef SUPPORTD3D
5755                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5756                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5757 #endif
5758                         break;
5759                 case RENDERPATH_D3D10:
5760                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5761                         break;
5762                 case RENDERPATH_D3D11:
5763                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5764                         break;
5765                 case RENDERPATH_GL11:
5766                 case RENDERPATH_GL13:
5767                 case RENDERPATH_GLES1:
5768 #ifndef USE_GLES2
5769                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5770 #endif
5771                         break;
5772                 case RENDERPATH_SOFT:
5773                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5774                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5775                         break;
5776                 case RENDERPATH_GL20:
5777                 case RENDERPATH_GLES2:
5778                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5779                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5780                         break;
5781                 }
5782         }
5783 }
5784
5785 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5786 {
5787         r_viewport_t viewport;
5788
5789         CHECKGLERROR
5790
5791         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5792         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);
5793         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5794         R_SetViewport(&viewport);
5795         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5796         GL_Color(1, 1, 1, 1);
5797         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5798         GL_BlendFunc(GL_ONE, GL_ZERO);
5799         GL_ScissorTest(false);
5800         GL_DepthMask(false);
5801         GL_DepthRange(0, 1);
5802         GL_DepthTest(false);
5803         GL_DepthFunc(GL_LEQUAL);
5804         R_EntityMatrix(&identitymatrix);
5805         R_Mesh_ResetTextureState();
5806         GL_PolygonOffset(0, 0);
5807         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5808         switch(vid.renderpath)
5809         {
5810         case RENDERPATH_GL11:
5811         case RENDERPATH_GL13:
5812         case RENDERPATH_GL20:
5813         case RENDERPATH_GLES1:
5814         case RENDERPATH_GLES2:
5815                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5816                 break;
5817         case RENDERPATH_D3D9:
5818         case RENDERPATH_D3D10:
5819         case RENDERPATH_D3D11:
5820         case RENDERPATH_SOFT:
5821                 break;
5822         }
5823         GL_CullFace(GL_NONE);
5824
5825         CHECKGLERROR
5826 }
5827
5828 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5829 {
5830         DrawQ_Finish();
5831
5832         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5833 }
5834
5835 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5836 {
5837         DrawQ_Finish();
5838
5839         R_SetupView(true, fbo, depthtexture, colortexture);
5840         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5841         GL_Color(1, 1, 1, 1);
5842         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5843         GL_BlendFunc(GL_ONE, GL_ZERO);
5844         GL_ScissorTest(true);
5845         GL_DepthMask(true);
5846         GL_DepthRange(0, 1);
5847         GL_DepthTest(true);
5848         GL_DepthFunc(GL_LEQUAL);
5849         R_EntityMatrix(&identitymatrix);
5850         R_Mesh_ResetTextureState();
5851         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5852         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5853         switch(vid.renderpath)
5854         {
5855         case RENDERPATH_GL11:
5856         case RENDERPATH_GL13:
5857         case RENDERPATH_GL20:
5858         case RENDERPATH_GLES1:
5859         case RENDERPATH_GLES2:
5860                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5861                 break;
5862         case RENDERPATH_D3D9:
5863         case RENDERPATH_D3D10:
5864         case RENDERPATH_D3D11:
5865         case RENDERPATH_SOFT:
5866                 break;
5867         }
5868         GL_CullFace(r_refdef.view.cullface_back);
5869 }
5870
5871 /*
5872 ================
5873 R_RenderView_UpdateViewVectors
5874 ================
5875 */
5876 void R_RenderView_UpdateViewVectors(void)
5877 {
5878         // break apart the view matrix into vectors for various purposes
5879         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5880         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5881         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5882         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5883         // make an inverted copy of the view matrix for tracking sprites
5884         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5885 }
5886
5887 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5888 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5889
5890 static void R_Water_StartFrame(void)
5891 {
5892         int i;
5893         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5894         r_waterstate_waterplane_t *p;
5895         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;
5896
5897         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5898                 return;
5899
5900         switch(vid.renderpath)
5901         {
5902         case RENDERPATH_GL20:
5903         case RENDERPATH_D3D9:
5904         case RENDERPATH_D3D10:
5905         case RENDERPATH_D3D11:
5906         case RENDERPATH_SOFT:
5907         case RENDERPATH_GLES2:
5908                 break;
5909         case RENDERPATH_GL11:
5910         case RENDERPATH_GL13:
5911         case RENDERPATH_GLES1:
5912                 return;
5913         }
5914
5915         // set waterwidth and waterheight to the water resolution that will be
5916         // used (often less than the screen resolution for faster rendering)
5917         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5918
5919         // calculate desired texture sizes
5920         // can't use water if the card does not support the texture size
5921         if (!r_water.integer || r_showsurfaces.integer)
5922                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5923         else if (vid.support.arb_texture_non_power_of_two)
5924         {
5925                 texturewidth = waterwidth;
5926                 textureheight = waterheight;
5927                 camerawidth = waterwidth;
5928                 cameraheight = waterheight;
5929         }
5930         else
5931         {
5932                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5933                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5934                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5935                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5936         }
5937
5938         // allocate textures as needed
5939         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))
5940         {
5941                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5942                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5943                 {
5944                         if (p->texture_refraction)
5945                                 R_FreeTexture(p->texture_refraction);
5946                         p->texture_refraction = NULL;
5947                         if (p->fbo_refraction)
5948                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5949                         p->fbo_refraction = 0;
5950                         if (p->texture_reflection)
5951                                 R_FreeTexture(p->texture_reflection);
5952                         p->texture_reflection = NULL;
5953                         if (p->fbo_reflection)
5954                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5955                         p->fbo_reflection = 0;
5956                         if (p->texture_camera)
5957                                 R_FreeTexture(p->texture_camera);
5958                         p->texture_camera = NULL;
5959                         if (p->fbo_camera)
5960                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5961                         p->fbo_camera = 0;
5962                 }
5963                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5964                 r_fb.water.texturewidth = texturewidth;
5965                 r_fb.water.textureheight = textureheight;
5966                 r_fb.water.camerawidth = camerawidth;
5967                 r_fb.water.cameraheight = cameraheight;
5968         }
5969
5970         if (r_fb.water.texturewidth)
5971         {
5972                 int scaledwidth, scaledheight;
5973
5974                 r_fb.water.enabled = true;
5975
5976                 // water resolution is usually reduced
5977                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5978                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5979                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5980
5981                 // set up variables that will be used in shader setup
5982                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5983                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5984                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5985                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5986         }
5987
5988         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5989         r_fb.water.numwaterplanes = 0;
5990 }
5991
5992 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5993 {
5994         int planeindex, bestplaneindex, vertexindex;
5995         vec3_t mins, maxs, normal, center, v, n;
5996         vec_t planescore, bestplanescore;
5997         mplane_t plane;
5998         r_waterstate_waterplane_t *p;
5999         texture_t *t = R_GetCurrentTexture(surface->texture);
6000
6001         rsurface.texture = t;
6002         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
6003         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
6004         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
6005                 return;
6006         // average the vertex normals, find the surface bounds (after deformvertexes)
6007         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6008         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6009         VectorCopy(n, normal);
6010         VectorCopy(v, mins);
6011         VectorCopy(v, maxs);
6012         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6013         {
6014                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6015                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6016                 VectorAdd(normal, n, normal);
6017                 mins[0] = min(mins[0], v[0]);
6018                 mins[1] = min(mins[1], v[1]);
6019                 mins[2] = min(mins[2], v[2]);
6020                 maxs[0] = max(maxs[0], v[0]);
6021                 maxs[1] = max(maxs[1], v[1]);
6022                 maxs[2] = max(maxs[2], v[2]);
6023         }
6024         VectorNormalize(normal);
6025         VectorMAM(0.5f, mins, 0.5f, maxs, center);
6026
6027         VectorCopy(normal, plane.normal);
6028         VectorNormalize(plane.normal);
6029         plane.dist = DotProduct(center, plane.normal);
6030         PlaneClassify(&plane);
6031         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6032         {
6033                 // skip backfaces (except if nocullface is set)
6034 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6035 //                      return;
6036                 VectorNegate(plane.normal, plane.normal);
6037                 plane.dist *= -1;
6038                 PlaneClassify(&plane);
6039         }
6040
6041
6042         // find a matching plane if there is one
6043         bestplaneindex = -1;
6044         bestplanescore = 1048576.0f;
6045         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6046         {
6047                 if(p->camera_entity == t->camera_entity)
6048                 {
6049                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6050                         if (bestplaneindex < 0 || bestplanescore > planescore)
6051                         {
6052                                 bestplaneindex = planeindex;
6053                                 bestplanescore = planescore;
6054                         }
6055                 }
6056         }
6057         planeindex = bestplaneindex;
6058
6059         // if this surface does not fit any known plane rendered this frame, add one
6060         if (planeindex < 0 || bestplanescore > 0.001f)
6061         {
6062                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6063                 {
6064                         // store the new plane
6065                         planeindex = r_fb.water.numwaterplanes++;
6066                         p = r_fb.water.waterplanes + planeindex;
6067                         p->plane = plane;
6068                         // clear materialflags and pvs
6069                         p->materialflags = 0;
6070                         p->pvsvalid = false;
6071                         p->camera_entity = t->camera_entity;
6072                         VectorCopy(mins, p->mins);
6073                         VectorCopy(maxs, p->maxs);
6074                 }
6075                 else
6076                 {
6077                         // We're totally screwed.
6078                         return;
6079                 }
6080         }
6081         else
6082         {
6083                 // merge mins/maxs when we're adding this surface to the plane
6084                 p = r_fb.water.waterplanes + planeindex;
6085                 p->mins[0] = min(p->mins[0], mins[0]);
6086                 p->mins[1] = min(p->mins[1], mins[1]);
6087                 p->mins[2] = min(p->mins[2], mins[2]);
6088                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6089                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6090                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6091         }
6092         // merge this surface's materialflags into the waterplane
6093         p->materialflags |= t->currentmaterialflags;
6094         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6095         {
6096                 // merge this surface's PVS into the waterplane
6097                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6098                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6099                 {
6100                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6101                         p->pvsvalid = true;
6102                 }
6103         }
6104 }
6105
6106 extern cvar_t r_drawparticles;
6107 extern cvar_t r_drawdecals;
6108
6109 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6110 {
6111         int myscissor[4];
6112         r_refdef_view_t originalview;
6113         r_refdef_view_t myview;
6114         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;
6115         r_waterstate_waterplane_t *p;
6116         vec3_t visorigin;
6117         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;
6118         char vabuf[1024];
6119
6120         originalview = r_refdef.view;
6121
6122         // lowquality hack, temporarily shut down some cvars and restore afterwards
6123         qualityreduction = r_water_lowquality.integer;
6124         if (qualityreduction > 0)
6125         {
6126                 if (qualityreduction >= 1)
6127                 {
6128                         old_r_shadows = r_shadows.integer;
6129                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6130                         old_r_dlight = r_shadow_realtime_dlight.integer;
6131                         Cvar_SetValueQuick(&r_shadows, 0);
6132                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6133                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6134                 }
6135                 if (qualityreduction >= 2)
6136                 {
6137                         old_r_dynamic = r_dynamic.integer;
6138                         old_r_particles = r_drawparticles.integer;
6139                         old_r_decals = r_drawdecals.integer;
6140                         Cvar_SetValueQuick(&r_dynamic, 0);
6141                         Cvar_SetValueQuick(&r_drawparticles, 0);
6142                         Cvar_SetValueQuick(&r_drawdecals, 0);
6143                 }
6144         }
6145
6146         // make sure enough textures are allocated
6147         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6148         {
6149                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6150                         continue;
6151                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6152                 {
6153                         if (!p->texture_refraction)
6154                                 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);
6155                         if (!p->texture_refraction)
6156                                 goto error;
6157                         if (usewaterfbo)
6158                         {
6159                                 if (r_fb.water.depthtexture == NULL)
6160                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6161                                 if (p->fbo_refraction == 0)
6162                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6163                         }
6164                 }
6165                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6166                 {
6167                         if (!p->texture_camera)
6168                                 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);
6169                         if (!p->texture_camera)
6170                                 goto error;
6171                         if (usewaterfbo)
6172                         {
6173                                 if (r_fb.water.depthtexture == NULL)
6174                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6175                                 if (p->fbo_camera == 0)
6176                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6177                         }
6178                 }
6179
6180                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6181                 {
6182                         if (!p->texture_reflection)
6183                                 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);
6184                         if (!p->texture_reflection)
6185                                 goto error;
6186                         if (usewaterfbo)
6187                         {
6188                                 if (r_fb.water.depthtexture == NULL)
6189                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6190                                 if (p->fbo_reflection == 0)
6191                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6192                         }
6193                 }
6194         }
6195
6196         // render views
6197         r_refdef.view = originalview;
6198         r_refdef.view.showdebug = false;
6199         r_refdef.view.width = r_fb.water.waterwidth;
6200         r_refdef.view.height = r_fb.water.waterheight;
6201         r_refdef.view.useclipplane = true;
6202         myview = r_refdef.view;
6203         r_fb.water.renderingscene = true;
6204         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6205         {
6206                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6207                         continue;
6208                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6209                 {
6210                         r_refdef.view = myview;
6211                         if(r_water_scissormode.integer)
6212                         {
6213                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6214                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6215                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6216                         }
6217
6218                         // render reflected scene and copy into texture
6219                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6220                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6221                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6222                         r_refdef.view.clipplane = p->plane;
6223                         // reverse the cullface settings for this render
6224                         r_refdef.view.cullface_front = GL_FRONT;
6225                         r_refdef.view.cullface_back = GL_BACK;
6226                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6227                         {
6228                                 r_refdef.view.usecustompvs = true;
6229                                 if (p->pvsvalid)
6230                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6231                                 else
6232                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6233                         }
6234
6235                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6236                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6237                         R_ClearScreen(r_refdef.fogenabled);
6238                         if(r_water_scissormode.integer & 2)
6239                                 R_View_UpdateWithScissor(myscissor);
6240                         else
6241                                 R_View_Update();
6242                         R_AnimCache_CacheVisibleEntities();
6243                         if(r_water_scissormode.integer & 1)
6244                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6245                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6246
6247                         if (!p->fbo_reflection)
6248                                 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);
6249                         r_fb.water.hideplayer = false;
6250                 }
6251
6252                 // render the normal view scene and copy into texture
6253                 // (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)
6254                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6255                 {
6256                         r_refdef.view = myview;
6257                         if(r_water_scissormode.integer)
6258                         {
6259                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6260                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6261                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6262                         }
6263
6264                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6265
6266                         r_refdef.view.clipplane = p->plane;
6267                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6268                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6269
6270                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6271                         {
6272                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6273                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6274                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6275                                 R_RenderView_UpdateViewVectors();
6276                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6277                                 {
6278                                         r_refdef.view.usecustompvs = true;
6279                                         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);
6280                                 }
6281                         }
6282
6283                         PlaneClassify(&r_refdef.view.clipplane);
6284
6285                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6286                         R_ClearScreen(r_refdef.fogenabled);
6287                         if(r_water_scissormode.integer & 2)
6288                                 R_View_UpdateWithScissor(myscissor);
6289                         else
6290                                 R_View_Update();
6291                         R_AnimCache_CacheVisibleEntities();
6292                         if(r_water_scissormode.integer & 1)
6293                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6294                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6295
6296                         if (!p->fbo_refraction)
6297                                 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);
6298                         r_fb.water.hideplayer = false;
6299                 }
6300                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6301                 {
6302                         r_refdef.view = myview;
6303
6304                         r_refdef.view.clipplane = p->plane;
6305                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6306                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6307
6308                         r_refdef.view.width = r_fb.water.camerawidth;
6309                         r_refdef.view.height = r_fb.water.cameraheight;
6310                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6311                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6312                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6313                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6314
6315                         if(p->camera_entity)
6316                         {
6317                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6318                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6319                         }
6320
6321                         // note: all of the view is used for displaying... so
6322                         // there is no use in scissoring
6323
6324                         // reverse the cullface settings for this render
6325                         r_refdef.view.cullface_front = GL_FRONT;
6326                         r_refdef.view.cullface_back = GL_BACK;
6327                         // also reverse the view matrix
6328                         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
6329                         R_RenderView_UpdateViewVectors();
6330                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6331                         {
6332                                 r_refdef.view.usecustompvs = true;
6333                                 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);
6334                         }
6335                         
6336                         // camera needs no clipplane
6337                         r_refdef.view.useclipplane = false;
6338
6339                         PlaneClassify(&r_refdef.view.clipplane);
6340
6341                         r_fb.water.hideplayer = false;
6342
6343                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6344                         R_ClearScreen(r_refdef.fogenabled);
6345                         R_View_Update();
6346                         R_AnimCache_CacheVisibleEntities();
6347                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6348
6349                         if (!p->fbo_camera)
6350                                 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);
6351                         r_fb.water.hideplayer = false;
6352                 }
6353
6354         }
6355         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6356         r_fb.water.renderingscene = false;
6357         r_refdef.view = originalview;
6358         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6359         if (!r_fb.water.depthtexture)
6360                 R_ClearScreen(r_refdef.fogenabled);
6361         R_View_Update();
6362         R_AnimCache_CacheVisibleEntities();
6363         goto finish;
6364 error:
6365         r_refdef.view = originalview;
6366         r_fb.water.renderingscene = false;
6367         Cvar_SetValueQuick(&r_water, 0);
6368         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6369 finish:
6370         // lowquality hack, restore cvars
6371         if (qualityreduction > 0)
6372         {
6373                 if (qualityreduction >= 1)
6374                 {
6375                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6376                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6377                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6378                 }
6379                 if (qualityreduction >= 2)
6380                 {
6381                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6382                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6383                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6384                 }
6385         }
6386 }
6387
6388 static void R_Bloom_StartFrame(void)
6389 {
6390         int i;
6391         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6392         int viewwidth, viewheight;
6393         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6394         textype_t textype = TEXTYPE_COLORBUFFER;
6395
6396         switch (vid.renderpath)
6397         {
6398         case RENDERPATH_GL20:
6399                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6400                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6401                 {
6402                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6403                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6404                 }
6405                 break;
6406         case RENDERPATH_GL11:
6407         case RENDERPATH_GL13:
6408         case RENDERPATH_GLES1:
6409         case RENDERPATH_GLES2:
6410         case RENDERPATH_D3D9:
6411         case RENDERPATH_D3D10:
6412         case RENDERPATH_D3D11:
6413                 r_fb.usedepthtextures = false;
6414                 break;
6415         case RENDERPATH_SOFT:
6416                 r_fb.usedepthtextures = true;
6417                 break;
6418         }
6419
6420         if (r_viewscale_fpsscaling.integer)
6421         {
6422                 double actualframetime;
6423                 double targetframetime;
6424                 double adjust;
6425                 actualframetime = r_refdef.lastdrawscreentime;
6426                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6427                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6428                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6429                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6430                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6431                 viewscalefpsadjusted += adjust;
6432                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6433         }
6434         else
6435                 viewscalefpsadjusted = 1.0f;
6436
6437         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6438
6439         switch(vid.renderpath)
6440         {
6441         case RENDERPATH_GL20:
6442         case RENDERPATH_D3D9:
6443         case RENDERPATH_D3D10:
6444         case RENDERPATH_D3D11:
6445         case RENDERPATH_SOFT:
6446         case RENDERPATH_GLES2:
6447                 break;
6448         case RENDERPATH_GL11:
6449         case RENDERPATH_GL13:
6450         case RENDERPATH_GLES1:
6451                 return;
6452         }
6453
6454         // set bloomwidth and bloomheight to the bloom resolution that will be
6455         // used (often less than the screen resolution for faster rendering)
6456         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6457         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6458         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6459         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6460         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6461
6462         // calculate desired texture sizes
6463         if (vid.support.arb_texture_non_power_of_two)
6464         {
6465                 screentexturewidth = vid.width;
6466                 screentextureheight = vid.height;
6467                 bloomtexturewidth = r_fb.bloomwidth;
6468                 bloomtextureheight = r_fb.bloomheight;
6469         }
6470         else
6471         {
6472                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6473                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6474                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6475                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6476         }
6477
6478         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))
6479         {
6480                 Cvar_SetValueQuick(&r_bloom, 0);
6481                 Cvar_SetValueQuick(&r_motionblur, 0);
6482                 Cvar_SetValueQuick(&r_damageblur, 0);
6483         }
6484
6485         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6486          && !r_bloom.integer
6487          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6488          && !useviewfbo
6489          && r_viewscale.value == 1.0f
6490          && !r_viewscale_fpsscaling.integer)
6491                 screentexturewidth = screentextureheight = 0;
6492         if (!r_bloom.integer)
6493                 bloomtexturewidth = bloomtextureheight = 0;
6494
6495         // allocate textures as needed
6496         if (r_fb.screentexturewidth != screentexturewidth
6497          || r_fb.screentextureheight != screentextureheight
6498          || r_fb.bloomtexturewidth != bloomtexturewidth
6499          || r_fb.bloomtextureheight != bloomtextureheight
6500          || r_fb.textype != textype
6501          || useviewfbo != (r_fb.fbo != 0))
6502         {
6503                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6504                 {
6505                         if (r_fb.bloomtexture[i])
6506                                 R_FreeTexture(r_fb.bloomtexture[i]);
6507                         r_fb.bloomtexture[i] = NULL;
6508
6509                         if (r_fb.bloomfbo[i])
6510                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6511                         r_fb.bloomfbo[i] = 0;
6512                 }
6513
6514                 if (r_fb.fbo)
6515                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6516                 r_fb.fbo = 0;
6517
6518                 if (r_fb.colortexture)
6519                         R_FreeTexture(r_fb.colortexture);
6520                 r_fb.colortexture = NULL;
6521
6522                 if (r_fb.depthtexture)
6523                         R_FreeTexture(r_fb.depthtexture);
6524                 r_fb.depthtexture = NULL;
6525
6526                 if (r_fb.ghosttexture)
6527                         R_FreeTexture(r_fb.ghosttexture);
6528                 r_fb.ghosttexture = NULL;
6529
6530                 r_fb.screentexturewidth = screentexturewidth;
6531                 r_fb.screentextureheight = screentextureheight;
6532                 r_fb.bloomtexturewidth = bloomtexturewidth;
6533                 r_fb.bloomtextureheight = bloomtextureheight;
6534                 r_fb.textype = textype;
6535
6536                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6537                 {
6538                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6539                                 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);
6540                         r_fb.ghosttexture_valid = false;
6541                         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);
6542                         if (useviewfbo)
6543                         {
6544                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6545                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6546                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6547                         }
6548                 }
6549
6550                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6551                 {
6552                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6553                         {
6554                                 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);
6555                                 if (useviewfbo)
6556                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6557                         }
6558                 }
6559         }
6560
6561         // bloom texture is a different resolution
6562         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6563         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6564         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6565         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6566         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6567
6568         // set up a texcoord array for the full resolution screen image
6569         // (we have to keep this around to copy back during final render)
6570         r_fb.screentexcoord2f[0] = 0;
6571         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6572         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6573         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6574         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6575         r_fb.screentexcoord2f[5] = 0;
6576         r_fb.screentexcoord2f[6] = 0;
6577         r_fb.screentexcoord2f[7] = 0;
6578
6579         if(r_fb.fbo) 
6580         {
6581                 for (i = 1;i < 8;i += 2)
6582                 {
6583                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6584                 }
6585         }
6586
6587         // set up a texcoord array for the reduced resolution bloom image
6588         // (which will be additive blended over the screen image)
6589         r_fb.bloomtexcoord2f[0] = 0;
6590         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6591         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6592         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6593         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6594         r_fb.bloomtexcoord2f[5] = 0;
6595         r_fb.bloomtexcoord2f[6] = 0;
6596         r_fb.bloomtexcoord2f[7] = 0;
6597
6598         switch(vid.renderpath)
6599         {
6600         case RENDERPATH_GL11:
6601         case RENDERPATH_GL13:
6602         case RENDERPATH_GL20:
6603         case RENDERPATH_SOFT:
6604         case RENDERPATH_GLES1:
6605         case RENDERPATH_GLES2:
6606                 break;
6607         case RENDERPATH_D3D9:
6608         case RENDERPATH_D3D10:
6609         case RENDERPATH_D3D11:
6610                 for (i = 0;i < 4;i++)
6611                 {
6612                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6613                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6614                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6615                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6616                 }
6617                 break;
6618         }
6619
6620         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6621
6622         if (r_fb.fbo)
6623                 r_refdef.view.clear = true;
6624 }
6625
6626 static void R_Bloom_MakeTexture(void)
6627 {
6628         int x, range, dir;
6629         float xoffset, yoffset, r, brighten;
6630         rtexture_t *intex;
6631         float colorscale = r_bloom_colorscale.value;
6632
6633         r_refdef.stats[r_stat_bloom]++;
6634     
6635 #if 0
6636     // this copy is unnecessary since it happens in R_BlendView already
6637         if (!r_fb.fbo)
6638         {
6639                 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);
6640                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6641         }
6642 #endif
6643
6644         // scale down screen texture to the bloom texture size
6645         CHECKGLERROR
6646         r_fb.bloomindex = 0;
6647         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6648         R_SetViewport(&r_fb.bloomviewport);
6649         GL_CullFace(GL_NONE);
6650         GL_DepthTest(false);
6651         GL_BlendFunc(GL_ONE, GL_ZERO);
6652         GL_Color(colorscale, colorscale, colorscale, 1);
6653         // 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...
6654         switch(vid.renderpath)
6655         {
6656         case RENDERPATH_GL11:
6657         case RENDERPATH_GL13:
6658         case RENDERPATH_GL20:
6659         case RENDERPATH_GLES1:
6660         case RENDERPATH_GLES2:
6661         case RENDERPATH_SOFT:
6662                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6663                 break;
6664         case RENDERPATH_D3D9:
6665         case RENDERPATH_D3D10:
6666         case RENDERPATH_D3D11:
6667                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6668                 break;
6669         }
6670         // TODO: do boxfilter scale-down in shader?
6671         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6672         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6673         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6674
6675         // we now have a properly scaled bloom image
6676         if (!r_fb.bloomfbo[r_fb.bloomindex])
6677         {
6678                 // copy it into the bloom texture
6679                 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);
6680                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6681         }
6682
6683         // multiply bloom image by itself as many times as desired
6684         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6685         {
6686                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6687                 r_fb.bloomindex ^= 1;
6688                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6689                 x *= 2;
6690                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6691                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6692                 {
6693                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6694                         GL_Color(r,r,r,1); // apply fix factor
6695                 }
6696                 else
6697                 {
6698                         if(x <= 2)
6699                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6700                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6701                         GL_Color(1,1,1,1); // no fix factor supported here
6702                 }
6703                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6704                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6705                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6706                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6707
6708                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6709                 {
6710                         // copy the darkened image to a texture
6711                         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);
6712                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6713                 }
6714         }
6715
6716         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6717         brighten = r_bloom_brighten.value;
6718         brighten = sqrt(brighten);
6719         if(range >= 1)
6720                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6721
6722         for (dir = 0;dir < 2;dir++)
6723         {
6724                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6725                 r_fb.bloomindex ^= 1;
6726                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6727                 // blend on at multiple vertical offsets to achieve a vertical blur
6728                 // TODO: do offset blends using GLSL
6729                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6730                 GL_BlendFunc(GL_ONE, GL_ZERO);
6731                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6732                 for (x = -range;x <= range;x++)
6733                 {
6734                         if (!dir){xoffset = 0;yoffset = x;}
6735                         else {xoffset = x;yoffset = 0;}
6736                         xoffset /= (float)r_fb.bloomtexturewidth;
6737                         yoffset /= (float)r_fb.bloomtextureheight;
6738                         // compute a texcoord array with the specified x and y offset
6739                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6740                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6741                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6742                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6743                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6744                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6745                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6746                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6747                         // this r value looks like a 'dot' particle, fading sharply to
6748                         // black at the edges
6749                         // (probably not realistic but looks good enough)
6750                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6751                         //r = brighten/(range*2+1);
6752                         r = brighten / (range * 2 + 1);
6753                         if(range >= 1)
6754                                 r *= (1 - x*x/(float)(range*range));
6755                         GL_Color(r, r, r, 1);
6756                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6757                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6758                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6759                         GL_BlendFunc(GL_ONE, GL_ONE);
6760                 }
6761
6762                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6763                 {
6764                         // copy the vertically or horizontally blurred bloom view to a texture
6765                         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);
6766                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6767                 }
6768         }
6769 }
6770
6771 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6772 {
6773         unsigned int permutation;
6774         float uservecs[4][4];
6775
6776         R_EntityMatrix(&identitymatrix);
6777
6778         switch (vid.renderpath)
6779         {
6780         case RENDERPATH_GL20:
6781         case RENDERPATH_D3D9:
6782         case RENDERPATH_D3D10:
6783         case RENDERPATH_D3D11:
6784         case RENDERPATH_SOFT:
6785         case RENDERPATH_GLES2:
6786                 permutation =
6787                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6788                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6789                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6790                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6791                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6792
6793                 if (r_fb.colortexture)
6794                 {
6795                         if (!r_fb.fbo)
6796                         {
6797                                 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);
6798                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6799                         }
6800
6801                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6802                         {
6803                                 // declare variables
6804                                 float blur_factor, blur_mouseaccel, blur_velocity;
6805                                 static float blur_average; 
6806                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6807
6808                                 // set a goal for the factoring
6809                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6810                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6811                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6812                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6813                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6814                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6815
6816                                 // from the goal, pick an averaged value between goal and last value
6817                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6818                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6819
6820                                 // enforce minimum amount of blur 
6821                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6822
6823                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6824
6825                                 // calculate values into a standard alpha
6826                                 cl.motionbluralpha = 1 - exp(-
6827                                                 (
6828                                                  (r_motionblur.value * blur_factor / 80)
6829                                                  +
6830                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6831                                                 )
6832                                                 /
6833                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6834                                           );
6835
6836                                 // randomization for the blur value to combat persistent ghosting
6837                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6838                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6839
6840                                 // apply the blur
6841                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6842                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6843                                 {
6844                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6845                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6846                                         switch(vid.renderpath)
6847                                         {
6848                                         case RENDERPATH_GL11:
6849                                         case RENDERPATH_GL13:
6850                                         case RENDERPATH_GL20:
6851                                         case RENDERPATH_GLES1:
6852                                         case RENDERPATH_GLES2:
6853                                         case RENDERPATH_SOFT:
6854                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6855                                                 break;
6856                                         case RENDERPATH_D3D9:
6857                                         case RENDERPATH_D3D10:
6858                                         case RENDERPATH_D3D11:
6859                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6860                                                 break;
6861                                         }
6862                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6863                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6864                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6865                                 }
6866
6867                                 // updates old view angles for next pass
6868                                 VectorCopy(cl.viewangles, blur_oldangles);
6869
6870                                 // copy view into the ghost texture
6871                                 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);
6872                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6873                                 r_fb.ghosttexture_valid = true;
6874                         }
6875                 }
6876                 else
6877                 {
6878                         // no r_fb.colortexture means we're rendering to the real fb
6879                         // we may still have to do view tint...
6880                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6881                         {
6882                                 // apply a color tint to the whole view
6883                                 R_ResetViewRendering2D(0, NULL, NULL);
6884                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6885                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6886                                 R_SetupShader_Generic_NoTexture(false, true);
6887                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6888                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6889                         }
6890                         break; // no screen processing, no bloom, skip it
6891                 }
6892
6893                 if (r_fb.bloomtexture[0])
6894                 {
6895                         // make the bloom texture
6896                         R_Bloom_MakeTexture();
6897                 }
6898
6899 #if _MSC_VER >= 1400
6900 #define sscanf sscanf_s
6901 #endif
6902                 memset(uservecs, 0, sizeof(uservecs));
6903                 if (r_glsl_postprocess_uservec1_enable.integer)
6904                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6905                 if (r_glsl_postprocess_uservec2_enable.integer)
6906                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6907                 if (r_glsl_postprocess_uservec3_enable.integer)
6908                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6909                 if (r_glsl_postprocess_uservec4_enable.integer)
6910                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6911
6912                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6913                 GL_Color(1, 1, 1, 1);
6914                 GL_BlendFunc(GL_ONE, GL_ZERO);
6915
6916                 switch(vid.renderpath)
6917                 {
6918                 case RENDERPATH_GL20:
6919                 case RENDERPATH_GLES2:
6920                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6921                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6922                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6923                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6924                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6925                         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]);
6926                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6927                         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]);
6928                         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]);
6929                         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]);
6930                         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]);
6931                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6932                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6933                         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);
6934                         break;
6935                 case RENDERPATH_D3D9:
6936 #ifdef SUPPORTD3D
6937                         // 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...
6938                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6939                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6940                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6941                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6942                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6943                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6944                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6945                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6946                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6947                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6948                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6949                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6950                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6951                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6952 #endif
6953                         break;
6954                 case RENDERPATH_D3D10:
6955                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6956                         break;
6957                 case RENDERPATH_D3D11:
6958                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6959                         break;
6960                 case RENDERPATH_SOFT:
6961                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6962                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6963                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6964                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6965                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6966                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6967                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6968                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6969                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6970                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6971                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6972                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6973                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6974                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6975                         break;
6976                 default:
6977                         break;
6978                 }
6979                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6980                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6981                 break;
6982         case RENDERPATH_GL11:
6983         case RENDERPATH_GL13:
6984         case RENDERPATH_GLES1:
6985                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6986                 {
6987                         // apply a color tint to the whole view
6988                         R_ResetViewRendering2D(0, NULL, NULL);
6989                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6990                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6991                         R_SetupShader_Generic_NoTexture(false, true);
6992                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6993                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6994                 }
6995                 break;
6996         }
6997 }
6998
6999 matrix4x4_t r_waterscrollmatrix;
7000
7001 void R_UpdateFog(void)
7002 {
7003         // Nehahra fog
7004         if (gamemode == GAME_NEHAHRA)
7005         {
7006                 if (gl_fogenable.integer)
7007                 {
7008                         r_refdef.oldgl_fogenable = true;
7009                         r_refdef.fog_density = gl_fogdensity.value;
7010                         r_refdef.fog_red = gl_fogred.value;
7011                         r_refdef.fog_green = gl_foggreen.value;
7012                         r_refdef.fog_blue = gl_fogblue.value;
7013                         r_refdef.fog_alpha = 1;
7014                         r_refdef.fog_start = 0;
7015                         r_refdef.fog_end = gl_skyclip.value;
7016                         r_refdef.fog_height = 1<<30;
7017                         r_refdef.fog_fadedepth = 128;
7018                 }
7019                 else if (r_refdef.oldgl_fogenable)
7020                 {
7021                         r_refdef.oldgl_fogenable = false;
7022                         r_refdef.fog_density = 0;
7023                         r_refdef.fog_red = 0;
7024                         r_refdef.fog_green = 0;
7025                         r_refdef.fog_blue = 0;
7026                         r_refdef.fog_alpha = 0;
7027                         r_refdef.fog_start = 0;
7028                         r_refdef.fog_end = 0;
7029                         r_refdef.fog_height = 1<<30;
7030                         r_refdef.fog_fadedepth = 128;
7031                 }
7032         }
7033
7034         // fog parms
7035         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7036         r_refdef.fog_start = max(0, r_refdef.fog_start);
7037         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7038
7039         if (r_refdef.fog_density && r_drawfog.integer)
7040         {
7041                 r_refdef.fogenabled = true;
7042                 // this is the point where the fog reaches 0.9986 alpha, which we
7043                 // consider a good enough cutoff point for the texture
7044                 // (0.9986 * 256 == 255.6)
7045                 if (r_fog_exp2.integer)
7046                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7047                 else
7048                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7049                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7050                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7051                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7052                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7053                         R_BuildFogHeightTexture();
7054                 // fog color was already set
7055                 // update the fog texture
7056                 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)
7057                         R_BuildFogTexture();
7058                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7059                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7060         }
7061         else
7062                 r_refdef.fogenabled = false;
7063
7064         // fog color
7065         if (r_refdef.fog_density)
7066         {
7067                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7068                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7069                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7070
7071                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7072                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7073                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7074                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7075
7076                 {
7077                         vec3_t fogvec;
7078                         VectorCopy(r_refdef.fogcolor, fogvec);
7079                         //   color.rgb *= ContrastBoost * SceneBrightness;
7080                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7081                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7082                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7083                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7084                 }
7085         }
7086 }
7087
7088 void R_UpdateVariables(void)
7089 {
7090         R_Textures_Frame();
7091
7092         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7093
7094         r_refdef.farclip = r_farclip_base.value;
7095         if (r_refdef.scene.worldmodel)
7096                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7097         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7098
7099         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7100                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7101         r_refdef.polygonfactor = 0;
7102         r_refdef.polygonoffset = 0;
7103         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7104         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7105
7106         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7107         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7108         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7109         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7110         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7111         if (FAKELIGHT_ENABLED)
7112         {
7113                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7114         }
7115         else if (r_refdef.scene.worldmodel)
7116         {
7117                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7118         }
7119         if (r_showsurfaces.integer)
7120         {
7121                 r_refdef.scene.rtworld = false;
7122                 r_refdef.scene.rtworldshadows = false;
7123                 r_refdef.scene.rtdlight = false;
7124                 r_refdef.scene.rtdlightshadows = false;
7125                 r_refdef.lightmapintensity = 0;
7126         }
7127
7128         r_gpuskeletal = false;
7129         switch(vid.renderpath)
7130         {
7131         case RENDERPATH_GL20:
7132                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7133         case RENDERPATH_D3D9:
7134         case RENDERPATH_D3D10:
7135         case RENDERPATH_D3D11:
7136         case RENDERPATH_SOFT:
7137         case RENDERPATH_GLES2:
7138                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7139                 {
7140                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7141                         {
7142                                 // build GLSL gamma texture
7143 #define RAMPWIDTH 256
7144                                 unsigned short ramp[RAMPWIDTH * 3];
7145                                 unsigned char rampbgr[RAMPWIDTH][4];
7146                                 int i;
7147
7148                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7149
7150                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7151                                 for(i = 0; i < RAMPWIDTH; ++i)
7152                                 {
7153                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7154                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7155                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7156                                         rampbgr[i][3] = 0;
7157                                 }
7158                                 if (r_texture_gammaramps)
7159                                 {
7160                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7161                                 }
7162                                 else
7163                                 {
7164                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7165                                 }
7166                         }
7167                 }
7168                 else
7169                 {
7170                         // remove GLSL gamma texture
7171                 }
7172                 break;
7173         case RENDERPATH_GL11:
7174         case RENDERPATH_GL13:
7175         case RENDERPATH_GLES1:
7176                 break;
7177         }
7178 }
7179
7180 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7181 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7182 /*
7183 ================
7184 R_SelectScene
7185 ================
7186 */
7187 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7188         if( scenetype != r_currentscenetype ) {
7189                 // store the old scenetype
7190                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7191                 r_currentscenetype = scenetype;
7192                 // move in the new scene
7193                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7194         }
7195 }
7196
7197 /*
7198 ================
7199 R_GetScenePointer
7200 ================
7201 */
7202 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7203 {
7204         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7205         if( scenetype == r_currentscenetype ) {
7206                 return &r_refdef.scene;
7207         } else {
7208                 return &r_scenes_store[ scenetype ];
7209         }
7210 }
7211
7212 static int R_SortEntities_Compare(const void *ap, const void *bp)
7213 {
7214         const entity_render_t *a = *(const entity_render_t **)ap;
7215         const entity_render_t *b = *(const entity_render_t **)bp;
7216
7217         // 1. compare model
7218         if(a->model < b->model)
7219                 return -1;
7220         if(a->model > b->model)
7221                 return +1;
7222
7223         // 2. compare skin
7224         // TODO possibly calculate the REAL skinnum here first using
7225         // skinscenes?
7226         if(a->skinnum < b->skinnum)
7227                 return -1;
7228         if(a->skinnum > b->skinnum)
7229                 return +1;
7230
7231         // everything we compared is equal
7232         return 0;
7233 }
7234 static void R_SortEntities(void)
7235 {
7236         // below or equal 2 ents, sorting never gains anything
7237         if(r_refdef.scene.numentities <= 2)
7238                 return;
7239         // sort
7240         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7241 }
7242
7243 /*
7244 ================
7245 R_RenderView
7246 ================
7247 */
7248 int dpsoftrast_test;
7249 extern cvar_t r_shadow_bouncegrid;
7250 void R_RenderView(void)
7251 {
7252         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7253         int fbo;
7254         rtexture_t *depthtexture;
7255         rtexture_t *colortexture;
7256
7257         dpsoftrast_test = r_test.integer;
7258
7259         if (r_timereport_active)
7260                 R_TimeReport("start");
7261         r_textureframe++; // used only by R_GetCurrentTexture
7262         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7263
7264         if(R_CompileShader_CheckStaticParms())
7265                 R_GLSL_Restart_f();
7266
7267         if (!r_drawentities.integer)
7268                 r_refdef.scene.numentities = 0;
7269         else if (r_sortentities.integer)
7270                 R_SortEntities();
7271
7272         R_AnimCache_ClearCache();
7273
7274         /* adjust for stereo display */
7275         if(R_Stereo_Active())
7276         {
7277                 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);
7278                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7279         }
7280
7281         if (r_refdef.view.isoverlay)
7282         {
7283                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7284                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7285                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7286                 R_TimeReport("depthclear");
7287
7288                 r_refdef.view.showdebug = false;
7289
7290                 r_fb.water.enabled = false;
7291                 r_fb.water.numwaterplanes = 0;
7292
7293                 R_RenderScene(0, NULL, NULL);
7294
7295                 r_refdef.view.matrix = originalmatrix;
7296
7297                 CHECKGLERROR
7298                 return;
7299         }
7300
7301         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7302         {
7303                 r_refdef.view.matrix = originalmatrix;
7304                 return;
7305         }
7306
7307         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7308
7309         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7310                 // in sRGB fallback, behave similar to true sRGB: convert this
7311                 // value from linear to sRGB
7312                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7313
7314         R_RenderView_UpdateViewVectors();
7315
7316         R_Shadow_UpdateWorldLightSelection();
7317
7318         R_Bloom_StartFrame();
7319
7320         // apply bloom brightness offset
7321         if(r_fb.bloomtexture[0])
7322                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7323
7324         R_Water_StartFrame();
7325
7326         // now we probably have an fbo to render into
7327         fbo = r_fb.fbo;
7328         depthtexture = r_fb.depthtexture;
7329         colortexture = r_fb.colortexture;
7330
7331         CHECKGLERROR
7332         if (r_timereport_active)
7333                 R_TimeReport("viewsetup");
7334
7335         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7336
7337         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7338         {
7339                 R_ClearScreen(r_refdef.fogenabled);
7340                 if (r_timereport_active)
7341                         R_TimeReport("viewclear");
7342         }
7343         r_refdef.view.clear = true;
7344
7345         r_refdef.view.showdebug = true;
7346
7347         R_View_Update();
7348         if (r_timereport_active)
7349                 R_TimeReport("visibility");
7350
7351         R_AnimCache_CacheVisibleEntities();
7352         if (r_timereport_active)
7353                 R_TimeReport("animcache");
7354
7355         R_Shadow_UpdateBounceGridTexture();
7356         if (r_timereport_active && r_shadow_bouncegrid.integer)
7357                 R_TimeReport("bouncegrid");
7358
7359         r_fb.water.numwaterplanes = 0;
7360         if (r_fb.water.enabled)
7361                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7362
7363         R_RenderScene(fbo, depthtexture, colortexture);
7364         r_fb.water.numwaterplanes = 0;
7365
7366         R_BlendView(fbo, depthtexture, colortexture);
7367         if (r_timereport_active)
7368                 R_TimeReport("blendview");
7369
7370         GL_Scissor(0, 0, vid.width, vid.height);
7371         GL_ScissorTest(false);
7372
7373         r_refdef.view.matrix = originalmatrix;
7374
7375         CHECKGLERROR
7376 }
7377
7378 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7379 {
7380         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7381         {
7382                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7383                 if (r_timereport_active)
7384                         R_TimeReport("waterworld");
7385         }
7386
7387         // don't let sound skip if going slow
7388         if (r_refdef.scene.extraupdate)
7389                 S_ExtraUpdate ();
7390
7391         R_DrawModelsAddWaterPlanes();
7392         if (r_timereport_active)
7393                 R_TimeReport("watermodels");
7394
7395         if (r_fb.water.numwaterplanes)
7396         {
7397                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7398                 if (r_timereport_active)
7399                         R_TimeReport("waterscenes");
7400         }
7401 }
7402
7403 extern cvar_t cl_locs_show;
7404 static void R_DrawLocs(void);
7405 static void R_DrawEntityBBoxes(void);
7406 static void R_DrawModelDecals(void);
7407 extern cvar_t cl_decals_newsystem;
7408 extern qboolean r_shadow_usingdeferredprepass;
7409 extern int r_shadow_shadowmapatlas_modelshadows_size;
7410 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7411 {
7412         qboolean shadowmapping = false;
7413
7414         if (r_timereport_active)
7415                 R_TimeReport("beginscene");
7416
7417         r_refdef.stats[r_stat_renders]++;
7418
7419         R_UpdateFog();
7420
7421         // don't let sound skip if going slow
7422         if (r_refdef.scene.extraupdate)
7423                 S_ExtraUpdate ();
7424
7425         R_MeshQueue_BeginScene();
7426
7427         R_SkyStartFrame();
7428
7429         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);
7430
7431         if (r_timereport_active)
7432                 R_TimeReport("skystartframe");
7433
7434         if (cl.csqc_vidvars.drawworld)
7435         {
7436                 // don't let sound skip if going slow
7437                 if (r_refdef.scene.extraupdate)
7438                         S_ExtraUpdate ();
7439
7440                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7441                 {
7442                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7443                         if (r_timereport_active)
7444                                 R_TimeReport("worldsky");
7445                 }
7446
7447                 if (R_DrawBrushModelsSky() && r_timereport_active)
7448                         R_TimeReport("bmodelsky");
7449
7450                 if (skyrendermasked && skyrenderlater)
7451                 {
7452                         // we have to force off the water clipping plane while rendering sky
7453                         R_SetupView(false, fbo, depthtexture, colortexture);
7454                         R_Sky();
7455                         R_SetupView(true, fbo, depthtexture, colortexture);
7456                         if (r_timereport_active)
7457                                 R_TimeReport("sky");
7458                 }
7459         }
7460
7461         R_Shadow_PrepareModelShadows();
7462         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7463         if (r_timereport_active)
7464                 R_TimeReport("preparelights");
7465
7466         // render all the shadowmaps that will be used for this view
7467         shadowmapping = R_Shadow_ShadowMappingEnabled();
7468         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7469         {
7470                 R_Shadow_DrawShadowMaps();
7471                 if (r_timereport_active)
7472                         R_TimeReport("shadowmaps");
7473         }
7474
7475         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7476         if (r_shadow_usingdeferredprepass)
7477                 R_Shadow_DrawPrepass();
7478
7479         // now we begin the forward pass of the view render
7480         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7481         {
7482                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7483                 if (r_timereport_active)
7484                         R_TimeReport("worlddepth");
7485         }
7486         if (r_depthfirst.integer >= 2)
7487         {
7488                 R_DrawModelsDepth();
7489                 if (r_timereport_active)
7490                         R_TimeReport("modeldepth");
7491         }
7492
7493         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7494         {
7495                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7496                 if (r_timereport_active)
7497                         R_TimeReport("world");
7498         }
7499
7500         // don't let sound skip if going slow
7501         if (r_refdef.scene.extraupdate)
7502                 S_ExtraUpdate ();
7503
7504         R_DrawModels();
7505         if (r_timereport_active)
7506                 R_TimeReport("models");
7507
7508         // don't let sound skip if going slow
7509         if (r_refdef.scene.extraupdate)
7510                 S_ExtraUpdate ();
7511
7512         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7513         {
7514                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7515                 R_Shadow_DrawModelShadows();
7516                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7517                 // don't let sound skip if going slow
7518                 if (r_refdef.scene.extraupdate)
7519                         S_ExtraUpdate ();
7520         }
7521
7522         if (!r_shadow_usingdeferredprepass)
7523         {
7524                 R_Shadow_DrawLights();
7525                 if (r_timereport_active)
7526                         R_TimeReport("rtlights");
7527         }
7528
7529         // don't let sound skip if going slow
7530         if (r_refdef.scene.extraupdate)
7531                 S_ExtraUpdate ();
7532
7533         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7534         {
7535                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7536                 R_Shadow_DrawModelShadows();
7537                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7538                 // don't let sound skip if going slow
7539                 if (r_refdef.scene.extraupdate)
7540                         S_ExtraUpdate ();
7541         }
7542
7543         if (cl.csqc_vidvars.drawworld)
7544         {
7545                 if (cl_decals_newsystem.integer)
7546                 {
7547                         R_DrawModelDecals();
7548                         if (r_timereport_active)
7549                                 R_TimeReport("modeldecals");
7550                 }
7551                 else
7552                 {
7553                         R_DrawDecals();
7554                         if (r_timereport_active)
7555                                 R_TimeReport("decals");
7556                 }
7557
7558                 R_DrawParticles();
7559                 if (r_timereport_active)
7560                         R_TimeReport("particles");
7561
7562                 R_DrawExplosions();
7563                 if (r_timereport_active)
7564                         R_TimeReport("explosions");
7565
7566                 R_DrawLightningBeams();
7567                 if (r_timereport_active)
7568                         R_TimeReport("lightning");
7569         }
7570
7571         if (cl.csqc_loaded)
7572                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7573
7574         if (r_refdef.view.showdebug)
7575         {
7576                 if (cl_locs_show.integer)
7577                 {
7578                         R_DrawLocs();
7579                         if (r_timereport_active)
7580                                 R_TimeReport("showlocs");
7581                 }
7582
7583                 if (r_drawportals.integer)
7584                 {
7585                         R_DrawPortals();
7586                         if (r_timereport_active)
7587                                 R_TimeReport("portals");
7588                 }
7589
7590                 if (r_showbboxes.value > 0)
7591                 {
7592                         R_DrawEntityBBoxes();
7593                         if (r_timereport_active)
7594                                 R_TimeReport("bboxes");
7595                 }
7596         }
7597
7598         if (r_transparent.integer)
7599         {
7600                 R_MeshQueue_RenderTransparent();
7601                 if (r_timereport_active)
7602                         R_TimeReport("drawtrans");
7603         }
7604
7605         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))
7606         {
7607                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7608                 if (r_timereport_active)
7609                         R_TimeReport("worlddebug");
7610                 R_DrawModelsDebug();
7611                 if (r_timereport_active)
7612                         R_TimeReport("modeldebug");
7613         }
7614
7615         if (cl.csqc_vidvars.drawworld)
7616         {
7617                 R_Shadow_DrawCoronas();
7618                 if (r_timereport_active)
7619                         R_TimeReport("coronas");
7620         }
7621
7622 #if 0
7623         {
7624                 GL_DepthTest(false);
7625                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7626                 GL_Color(1, 1, 1, 1);
7627                 qglBegin(GL_POLYGON);
7628                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7629                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7630                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7631                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7632                 qglEnd();
7633                 qglBegin(GL_POLYGON);
7634                 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]);
7635                 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]);
7636                 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]);
7637                 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]);
7638                 qglEnd();
7639                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7640         }
7641 #endif
7642
7643         // don't let sound skip if going slow
7644         if (r_refdef.scene.extraupdate)
7645                 S_ExtraUpdate ();
7646 }
7647
7648 static const unsigned short bboxelements[36] =
7649 {
7650         5, 1, 3, 5, 3, 7,
7651         6, 2, 0, 6, 0, 4,
7652         7, 3, 2, 7, 2, 6,
7653         4, 0, 1, 4, 1, 5,
7654         4, 5, 7, 4, 7, 6,
7655         1, 0, 2, 1, 2, 3,
7656 };
7657
7658 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7659 {
7660         int i;
7661         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7662
7663         RSurf_ActiveWorldEntity();
7664
7665         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7666         GL_DepthMask(false);
7667         GL_DepthRange(0, 1);
7668         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7669 //      R_Mesh_ResetTextureState();
7670
7671         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7672         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7673         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7674         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7675         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7676         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7677         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7678         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7679         R_FillColors(color4f, 8, cr, cg, cb, ca);
7680         if (r_refdef.fogenabled)
7681         {
7682                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7683                 {
7684                         f1 = RSurf_FogVertex(v);
7685                         f2 = 1 - f1;
7686                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7687                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7688                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7689                 }
7690         }
7691         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7692         R_Mesh_ResetTextureState();
7693         R_SetupShader_Generic_NoTexture(false, false);
7694         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7695 }
7696
7697 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7698 {
7699         prvm_prog_t *prog = SVVM_prog;
7700         int i;
7701         float color[4];
7702         prvm_edict_t *edict;
7703
7704         // this function draws bounding boxes of server entities
7705         if (!sv.active)
7706                 return;
7707
7708         GL_CullFace(GL_NONE);
7709         R_SetupShader_Generic_NoTexture(false, false);
7710
7711         for (i = 0;i < numsurfaces;i++)
7712         {
7713                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7714                 switch ((int)PRVM_serveredictfloat(edict, solid))
7715                 {
7716                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7717                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7718                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7719                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7720                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7721                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7722                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7723                 }
7724                 color[3] *= r_showbboxes.value;
7725                 color[3] = bound(0, color[3], 1);
7726                 GL_DepthTest(!r_showdisabledepthtest.integer);
7727                 GL_CullFace(r_refdef.view.cullface_front);
7728                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7729         }
7730 }
7731
7732 static void R_DrawEntityBBoxes(void)
7733 {
7734         int i;
7735         prvm_edict_t *edict;
7736         vec3_t center;
7737         prvm_prog_t *prog = SVVM_prog;
7738
7739         // this function draws bounding boxes of server entities
7740         if (!sv.active)
7741                 return;
7742
7743         for (i = 0;i < prog->num_edicts;i++)
7744         {
7745                 edict = PRVM_EDICT_NUM(i);
7746                 if (edict->priv.server->free)
7747                         continue;
7748                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7749                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7750                         continue;
7751                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7752                         continue;
7753                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7754                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7755         }
7756 }
7757
7758 static const int nomodelelement3i[24] =
7759 {
7760         5, 2, 0,
7761         5, 1, 2,
7762         5, 0, 3,
7763         5, 3, 1,
7764         0, 2, 4,
7765         2, 1, 4,
7766         3, 0, 4,
7767         1, 3, 4
7768 };
7769
7770 static const unsigned short nomodelelement3s[24] =
7771 {
7772         5, 2, 0,
7773         5, 1, 2,
7774         5, 0, 3,
7775         5, 3, 1,
7776         0, 2, 4,
7777         2, 1, 4,
7778         3, 0, 4,
7779         1, 3, 4
7780 };
7781
7782 static const float nomodelvertex3f[6*3] =
7783 {
7784         -16,   0,   0,
7785          16,   0,   0,
7786           0, -16,   0,
7787           0,  16,   0,
7788           0,   0, -16,
7789           0,   0,  16
7790 };
7791
7792 static const float nomodelcolor4f[6*4] =
7793 {
7794         0.0f, 0.0f, 0.5f, 1.0f,
7795         0.0f, 0.0f, 0.5f, 1.0f,
7796         0.0f, 0.5f, 0.0f, 1.0f,
7797         0.0f, 0.5f, 0.0f, 1.0f,
7798         0.5f, 0.0f, 0.0f, 1.0f,
7799         0.5f, 0.0f, 0.0f, 1.0f
7800 };
7801
7802 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7803 {
7804         int i;
7805         float f1, f2, *c;
7806         float color4f[6*4];
7807
7808         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);
7809
7810         // this is only called once per entity so numsurfaces is always 1, and
7811         // surfacelist is always {0}, so this code does not handle batches
7812
7813         if (rsurface.ent_flags & RENDER_ADDITIVE)
7814         {
7815                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7816                 GL_DepthMask(false);
7817         }
7818         else if (rsurface.colormod[3] < 1)
7819         {
7820                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7821                 GL_DepthMask(false);
7822         }
7823         else
7824         {
7825                 GL_BlendFunc(GL_ONE, GL_ZERO);
7826                 GL_DepthMask(true);
7827         }
7828         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7829         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7830         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7831         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7832         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7833         for (i = 0, c = color4f;i < 6;i++, c += 4)
7834         {
7835                 c[0] *= rsurface.colormod[0];
7836                 c[1] *= rsurface.colormod[1];
7837                 c[2] *= rsurface.colormod[2];
7838                 c[3] *= rsurface.colormod[3];
7839         }
7840         if (r_refdef.fogenabled)
7841         {
7842                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7843                 {
7844                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7845                         f2 = 1 - f1;
7846                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7847                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7848                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7849                 }
7850         }
7851 //      R_Mesh_ResetTextureState();
7852         R_SetupShader_Generic_NoTexture(false, false);
7853         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7854         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7855 }
7856
7857 void R_DrawNoModel(entity_render_t *ent)
7858 {
7859         vec3_t org;
7860         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7861         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7862                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7863         else
7864                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7865 }
7866
7867 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7868 {
7869         vec3_t right1, right2, diff, normal;
7870
7871         VectorSubtract (org2, org1, normal);
7872
7873         // calculate 'right' vector for start
7874         VectorSubtract (r_refdef.view.origin, org1, diff);
7875         CrossProduct (normal, diff, right1);
7876         VectorNormalize (right1);
7877
7878         // calculate 'right' vector for end
7879         VectorSubtract (r_refdef.view.origin, org2, diff);
7880         CrossProduct (normal, diff, right2);
7881         VectorNormalize (right2);
7882
7883         vert[ 0] = org1[0] + width * right1[0];
7884         vert[ 1] = org1[1] + width * right1[1];
7885         vert[ 2] = org1[2] + width * right1[2];
7886         vert[ 3] = org1[0] - width * right1[0];
7887         vert[ 4] = org1[1] - width * right1[1];
7888         vert[ 5] = org1[2] - width * right1[2];
7889         vert[ 6] = org2[0] - width * right2[0];
7890         vert[ 7] = org2[1] - width * right2[1];
7891         vert[ 8] = org2[2] - width * right2[2];
7892         vert[ 9] = org2[0] + width * right2[0];
7893         vert[10] = org2[1] + width * right2[1];
7894         vert[11] = org2[2] + width * right2[2];
7895 }
7896
7897 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)
7898 {
7899         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7900         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7901         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7902         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7903         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7904         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7905         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7906         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7907         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7908         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7909         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7910         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7911 }
7912
7913 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7914 {
7915         int i;
7916         float *vertex3f;
7917         float v[3];
7918         VectorSet(v, x, y, z);
7919         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7920                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7921                         break;
7922         if (i == mesh->numvertices)
7923         {
7924                 if (mesh->numvertices < mesh->maxvertices)
7925                 {
7926                         VectorCopy(v, vertex3f);
7927                         mesh->numvertices++;
7928                 }
7929                 return mesh->numvertices;
7930         }
7931         else
7932                 return i;
7933 }
7934
7935 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7936 {
7937         int i;
7938         int *e, element[3];
7939         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7940         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7941         e = mesh->element3i + mesh->numtriangles * 3;
7942         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7943         {
7944                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7945                 if (mesh->numtriangles < mesh->maxtriangles)
7946                 {
7947                         *e++ = element[0];
7948                         *e++ = element[1];
7949                         *e++ = element[2];
7950                         mesh->numtriangles++;
7951                 }
7952                 element[1] = element[2];
7953         }
7954 }
7955
7956 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7957 {
7958         int i;
7959         int *e, element[3];
7960         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7961         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7962         e = mesh->element3i + mesh->numtriangles * 3;
7963         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7964         {
7965                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7966                 if (mesh->numtriangles < mesh->maxtriangles)
7967                 {
7968                         *e++ = element[0];
7969                         *e++ = element[1];
7970                         *e++ = element[2];
7971                         mesh->numtriangles++;
7972                 }
7973                 element[1] = element[2];
7974         }
7975 }
7976
7977 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7978 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7979 {
7980         int planenum, planenum2;
7981         int w;
7982         int tempnumpoints;
7983         mplane_t *plane, *plane2;
7984         double maxdist;
7985         double temppoints[2][256*3];
7986         // figure out how large a bounding box we need to properly compute this brush
7987         maxdist = 0;
7988         for (w = 0;w < numplanes;w++)
7989                 maxdist = max(maxdist, fabs(planes[w].dist));
7990         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7991         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7992         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7993         {
7994                 w = 0;
7995                 tempnumpoints = 4;
7996                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7997                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7998                 {
7999                         if (planenum2 == planenum)
8000                                 continue;
8001                         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);
8002                         w = !w;
8003                 }
8004                 if (tempnumpoints < 3)
8005                         continue;
8006                 // generate elements forming a triangle fan for this polygon
8007                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8008         }
8009 }
8010
8011 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)
8012 {
8013         texturelayer_t *layer;
8014         layer = t->currentlayers + t->currentnumlayers++;
8015         layer->type = type;
8016         layer->depthmask = depthmask;
8017         layer->blendfunc1 = blendfunc1;
8018         layer->blendfunc2 = blendfunc2;
8019         layer->texture = texture;
8020         layer->texmatrix = *matrix;
8021         layer->color[0] = r;
8022         layer->color[1] = g;
8023         layer->color[2] = b;
8024         layer->color[3] = a;
8025 }
8026
8027 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8028 {
8029         if(parms[0] == 0 && parms[1] == 0)
8030                 return false;
8031         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8032                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8033                         return false;
8034         return true;
8035 }
8036
8037 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8038 {
8039         double index, f;
8040         index = parms[2] + rsurface.shadertime * parms[3];
8041         index -= floor(index);
8042         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8043         {
8044         default:
8045         case Q3WAVEFUNC_NONE:
8046         case Q3WAVEFUNC_NOISE:
8047         case Q3WAVEFUNC_COUNT:
8048                 f = 0;
8049                 break;
8050         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8051         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8052         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8053         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8054         case Q3WAVEFUNC_TRIANGLE:
8055                 index *= 4;
8056                 f = index - floor(index);
8057                 if (index < 1)
8058                 {
8059                         // f = f;
8060                 }
8061                 else if (index < 2)
8062                         f = 1 - f;
8063                 else if (index < 3)
8064                         f = -f;
8065                 else
8066                         f = -(1 - f);
8067                 break;
8068         }
8069         f = parms[0] + parms[1] * f;
8070         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8071                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8072         return (float) f;
8073 }
8074
8075 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8076 {
8077         int w, h, idx;
8078         float shadertime;
8079         float f;
8080         float offsetd[2];
8081         float tcmat[12];
8082         matrix4x4_t matrix, temp;
8083         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8084         // it's better to have one huge fixup every 9 hours than gradual
8085         // degradation over time which looks consistently bad after many hours.
8086         //
8087         // tcmod scroll in particular suffers from this degradation which can't be
8088         // effectively worked around even with floor() tricks because we don't
8089         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8090         // a workaround involving floor() would be incorrect anyway...
8091         shadertime = rsurface.shadertime;
8092         if (shadertime >= 32768.0f)
8093                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8094         switch(tcmod->tcmod)
8095         {
8096                 case Q3TCMOD_COUNT:
8097                 case Q3TCMOD_NONE:
8098                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8099                                 matrix = r_waterscrollmatrix;
8100                         else
8101                                 matrix = identitymatrix;
8102                         break;
8103                 case Q3TCMOD_ENTITYTRANSLATE:
8104                         // this is used in Q3 to allow the gamecode to control texcoord
8105                         // scrolling on the entity, which is not supported in darkplaces yet.
8106                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8107                         break;
8108                 case Q3TCMOD_ROTATE:
8109                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8110                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8111                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8112                         break;
8113                 case Q3TCMOD_SCALE:
8114                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8115                         break;
8116                 case Q3TCMOD_SCROLL:
8117                         // this particular tcmod is a "bug for bug" compatible one with regards to
8118                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8119                         // specifically did the wrapping and so we must mimic that...
8120                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8121                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8122                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8123                         break;
8124                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8125                         w = (int) tcmod->parms[0];
8126                         h = (int) tcmod->parms[1];
8127                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8128                         f = f - floor(f);
8129                         idx = (int) floor(f * w * h);
8130                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8131                         break;
8132                 case Q3TCMOD_STRETCH:
8133                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8134                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8135                         break;
8136                 case Q3TCMOD_TRANSFORM:
8137                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8138                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8139                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8140                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8141                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8142                         break;
8143                 case Q3TCMOD_TURBULENT:
8144                         // this is handled in the RSurf_PrepareVertices function
8145                         matrix = identitymatrix;
8146                         break;
8147         }
8148         temp = *texmatrix;
8149         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8150 }
8151
8152 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8153 {
8154         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8155         char name[MAX_QPATH];
8156         skinframe_t *skinframe;
8157         unsigned char pixels[296*194];
8158         strlcpy(cache->name, skinname, sizeof(cache->name));
8159         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8160         if (developer_loading.integer)
8161                 Con_Printf("loading %s\n", name);
8162         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8163         if (!skinframe || !skinframe->base)
8164         {
8165                 unsigned char *f;
8166                 fs_offset_t filesize;
8167                 skinframe = NULL;
8168                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8169                 if (f)
8170                 {
8171                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8172                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8173                         Mem_Free(f);
8174                 }
8175         }
8176         cache->skinframe = skinframe;
8177 }
8178
8179 texture_t *R_GetCurrentTexture(texture_t *t)
8180 {
8181         int i;
8182         const entity_render_t *ent = rsurface.entity;
8183         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8184         q3shaderinfo_layer_tcmod_t *tcmod;
8185
8186         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8187                 return t->currentframe;
8188         t->update_lastrenderframe = r_textureframe;
8189         t->update_lastrenderentity = (void *)ent;
8190
8191         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8192                 t->camera_entity = ent->entitynumber;
8193         else
8194                 t->camera_entity = 0;
8195
8196         // switch to an alternate material if this is a q1bsp animated material
8197         {
8198                 texture_t *texture = t;
8199                 int s = rsurface.ent_skinnum;
8200                 if ((unsigned int)s >= (unsigned int)model->numskins)
8201                         s = 0;
8202                 if (model->skinscenes)
8203                 {
8204                         if (model->skinscenes[s].framecount > 1)
8205                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8206                         else
8207                                 s = model->skinscenes[s].firstframe;
8208                 }
8209                 if (s > 0)
8210                         t = t + s * model->num_surfaces;
8211                 if (t->animated)
8212                 {
8213                         // use an alternate animation if the entity's frame is not 0,
8214                         // and only if the texture has an alternate animation
8215                         if (t->animated == 2) // q2bsp
8216                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8217                         else if (rsurface.ent_alttextures && t->anim_total[1])
8218                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8219                         else
8220                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8221                 }
8222                 texture->currentframe = t;
8223         }
8224
8225         // update currentskinframe to be a qw skin or animation frame
8226         if (rsurface.ent_qwskin >= 0)
8227         {
8228                 i = rsurface.ent_qwskin;
8229                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8230                 {
8231                         r_qwskincache_size = cl.maxclients;
8232                         if (r_qwskincache)
8233                                 Mem_Free(r_qwskincache);
8234                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8235                 }
8236                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8237                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8238                 t->currentskinframe = r_qwskincache[i].skinframe;
8239                 if (t->materialshaderpass && t->currentskinframe == NULL)
8240                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8241         }
8242         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8243                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8244         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8245                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8246
8247         t->currentmaterialflags = t->basematerialflags;
8248         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8249         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8250                 t->currentalpha *= r_wateralpha.value;
8251         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8252                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8253         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8254                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8255         if (!(rsurface.ent_flags & RENDER_LIGHT))
8256                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8257         else if (FAKELIGHT_ENABLED)
8258         {
8259                 // no modellight if using fakelight for the map
8260         }
8261         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8262         {
8263                 // pick a model lighting mode
8264                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8265                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8266                 else
8267                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8268         }
8269         if (rsurface.ent_flags & RENDER_ADDITIVE)
8270                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8271         else if (t->currentalpha < 1)
8272                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8273         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8274         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8275                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8276         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8277                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8278         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8279                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8280         if (t->backgroundshaderpass)
8281                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8282         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8283         {
8284                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8285                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8286         }
8287         else
8288                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8289         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8290         {
8291                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8292                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8293         }
8294         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8295                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8296
8297         // there is no tcmod
8298         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8299         {
8300                 t->currenttexmatrix = r_waterscrollmatrix;
8301                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8302         }
8303         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8304         {
8305                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8306                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8307         }
8308
8309         if (t->materialshaderpass)
8310                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8311                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8312
8313         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8314         if (t->currentskinframe->qpixels)
8315                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8316         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8317         if (!t->basetexture)
8318                 t->basetexture = r_texture_notexture;
8319         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8320         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8321         t->nmaptexture = t->currentskinframe->nmap;
8322         if (!t->nmaptexture)
8323                 t->nmaptexture = r_texture_blanknormalmap;
8324         t->glosstexture = r_texture_black;
8325         t->glowtexture = t->currentskinframe->glow;
8326         t->fogtexture = t->currentskinframe->fog;
8327         t->reflectmasktexture = t->currentskinframe->reflect;
8328         if (t->backgroundshaderpass)
8329         {
8330                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8331                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8332                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8333                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8334                 t->backgroundglosstexture = r_texture_black;
8335                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8336                 if (!t->backgroundnmaptexture)
8337                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8338                 // make sure that if glow is going to be used, both textures are not NULL
8339                 if (!t->backgroundglowtexture && t->glowtexture)
8340                         t->backgroundglowtexture = r_texture_black;
8341                 if (!t->glowtexture && t->backgroundglowtexture)
8342                         t->glowtexture = r_texture_black;
8343         }
8344         else
8345         {
8346                 t->backgroundbasetexture = r_texture_white;
8347                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8348                 t->backgroundglosstexture = r_texture_black;
8349                 t->backgroundglowtexture = NULL;
8350         }
8351         t->specularpower = r_shadow_glossexponent.value;
8352         // TODO: store reference values for these in the texture?
8353         t->specularscale = 0;
8354         if (r_shadow_gloss.integer > 0)
8355         {
8356                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8357                 {
8358                         if (r_shadow_glossintensity.value > 0)
8359                         {
8360                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8361                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8362                                 t->specularscale = r_shadow_glossintensity.value;
8363                         }
8364                 }
8365                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8366                 {
8367                         t->glosstexture = r_texture_white;
8368                         t->backgroundglosstexture = r_texture_white;
8369                         t->specularscale = r_shadow_gloss2intensity.value;
8370                         t->specularpower = r_shadow_gloss2exponent.value;
8371                 }
8372         }
8373         t->specularscale *= t->specularscalemod;
8374         t->specularpower *= t->specularpowermod;
8375         t->rtlightambient = 0;
8376
8377         // lightmaps mode looks bad with dlights using actual texturing, so turn
8378         // off the colormap and glossmap, but leave the normalmap on as it still
8379         // accurately represents the shading involved
8380         if (gl_lightmaps.integer)
8381         {
8382                 t->basetexture = r_texture_grey128;
8383                 t->pantstexture = r_texture_black;
8384                 t->shirttexture = r_texture_black;
8385                 if (gl_lightmaps.integer < 2)
8386                         t->nmaptexture = r_texture_blanknormalmap;
8387                 t->glosstexture = r_texture_black;
8388                 t->glowtexture = NULL;
8389                 t->fogtexture = NULL;
8390                 t->reflectmasktexture = NULL;
8391                 t->backgroundbasetexture = NULL;
8392                 if (gl_lightmaps.integer < 2)
8393                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8394                 t->backgroundglosstexture = r_texture_black;
8395                 t->backgroundglowtexture = NULL;
8396                 t->specularscale = 0;
8397                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8398         }
8399
8400         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8401         VectorClear(t->dlightcolor);
8402         t->currentnumlayers = 0;
8403         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8404         {
8405                 int blendfunc1, blendfunc2;
8406                 qboolean depthmask;
8407                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8408                 {
8409                         blendfunc1 = GL_SRC_ALPHA;
8410                         blendfunc2 = GL_ONE;
8411                 }
8412                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8413                 {
8414                         blendfunc1 = GL_SRC_ALPHA;
8415                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8416                 }
8417                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8418                 {
8419                         blendfunc1 = t->customblendfunc[0];
8420                         blendfunc2 = t->customblendfunc[1];
8421                 }
8422                 else
8423                 {
8424                         blendfunc1 = GL_ONE;
8425                         blendfunc2 = GL_ZERO;
8426                 }
8427                 // don't colormod evilblend textures
8428                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8429                         VectorSet(t->lightmapcolor, 1, 1, 1);
8430                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8431                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8432                 {
8433                         // fullbright is not affected by r_refdef.lightmapintensity
8434                         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]);
8435                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8436                                 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]);
8437                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8438                                 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]);
8439                 }
8440                 else
8441                 {
8442                         vec3_t ambientcolor;
8443                         float colorscale;
8444                         // set the color tint used for lights affecting this surface
8445                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8446                         colorscale = 2;
8447                         // q3bsp has no lightmap updates, so the lightstylevalue that
8448                         // would normally be baked into the lightmap must be
8449                         // applied to the color
8450                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8451                         if (model->type == mod_brushq3)
8452                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8453                         colorscale *= r_refdef.lightmapintensity;
8454                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8455                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8456                         // basic lit geometry
8457                         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]);
8458                         // add pants/shirt if needed
8459                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8460                                 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]);
8461                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8462                                 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]);
8463                         // now add ambient passes if needed
8464                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8465                         {
8466                                 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]);
8467                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8468                                         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]);
8469                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8470                                         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]);
8471                         }
8472                 }
8473                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8474                         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]);
8475                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8476                 {
8477                         // if this is opaque use alpha blend which will darken the earlier
8478                         // passes cheaply.
8479                         //
8480                         // if this is an alpha blended material, all the earlier passes
8481                         // were darkened by fog already, so we only need to add the fog
8482                         // color ontop through the fog mask texture
8483                         //
8484                         // if this is an additive blended material, all the earlier passes
8485                         // were darkened by fog already, and we should not add fog color
8486                         // (because the background was not darkened, there is no fog color
8487                         // that was lost behind it).
8488                         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]);
8489                 }
8490         }
8491
8492         return t;
8493 }
8494
8495 rsurfacestate_t rsurface;
8496
8497 void RSurf_ActiveWorldEntity(void)
8498 {
8499         dp_model_t *model = r_refdef.scene.worldmodel;
8500         //if (rsurface.entity == r_refdef.scene.worldentity)
8501         //      return;
8502         rsurface.entity = r_refdef.scene.worldentity;
8503         rsurface.skeleton = NULL;
8504         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8505         rsurface.ent_skinnum = 0;
8506         rsurface.ent_qwskin = -1;
8507         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8508         rsurface.shadertime = r_refdef.scene.time;
8509         rsurface.matrix = identitymatrix;
8510         rsurface.inversematrix = identitymatrix;
8511         rsurface.matrixscale = 1;
8512         rsurface.inversematrixscale = 1;
8513         R_EntityMatrix(&identitymatrix);
8514         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8515         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8516         rsurface.fograngerecip = r_refdef.fograngerecip;
8517         rsurface.fogheightfade = r_refdef.fogheightfade;
8518         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8519         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8520         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8521         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8522         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8523         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8524         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8525         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8526         rsurface.colormod[3] = 1;
8527         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);
8528         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8529         rsurface.frameblend[0].lerp = 1;
8530         rsurface.ent_alttextures = false;
8531         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8532         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8533         rsurface.entityskeletaltransform3x4 = NULL;
8534         rsurface.entityskeletaltransform3x4buffer = NULL;
8535         rsurface.entityskeletaltransform3x4offset = 0;
8536         rsurface.entityskeletaltransform3x4size = 0;;
8537         rsurface.entityskeletalnumtransforms = 0;
8538         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8539         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8540         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8541         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8542         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8543         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8544         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8545         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8546         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8547         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8548         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8549         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8550         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8551         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8552         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8553         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8554         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8555         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8556         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8557         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8558         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8559         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8560         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8561         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8562         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8563         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8564         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8565         rsurface.modelelement3i = model->surfmesh.data_element3i;
8566         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8567         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8568         rsurface.modelelement3s = model->surfmesh.data_element3s;
8569         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8570         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8571         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8572         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8573         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8574         rsurface.modelsurfaces = model->data_surfaces;
8575         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8576         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8577         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8578         rsurface.modelgeneratedvertex = false;
8579         rsurface.batchgeneratedvertex = false;
8580         rsurface.batchfirstvertex = 0;
8581         rsurface.batchnumvertices = 0;
8582         rsurface.batchfirsttriangle = 0;
8583         rsurface.batchnumtriangles = 0;
8584         rsurface.batchvertex3f  = NULL;
8585         rsurface.batchvertex3f_vertexbuffer = NULL;
8586         rsurface.batchvertex3f_bufferoffset = 0;
8587         rsurface.batchsvector3f = NULL;
8588         rsurface.batchsvector3f_vertexbuffer = NULL;
8589         rsurface.batchsvector3f_bufferoffset = 0;
8590         rsurface.batchtvector3f = NULL;
8591         rsurface.batchtvector3f_vertexbuffer = NULL;
8592         rsurface.batchtvector3f_bufferoffset = 0;
8593         rsurface.batchnormal3f  = NULL;
8594         rsurface.batchnormal3f_vertexbuffer = NULL;
8595         rsurface.batchnormal3f_bufferoffset = 0;
8596         rsurface.batchlightmapcolor4f = NULL;
8597         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8598         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8599         rsurface.batchtexcoordtexture2f = NULL;
8600         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8601         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8602         rsurface.batchtexcoordlightmap2f = NULL;
8603         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8604         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8605         rsurface.batchskeletalindex4ub = NULL;
8606         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8607         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8608         rsurface.batchskeletalweight4ub = NULL;
8609         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8610         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8611         rsurface.batchvertexmesh = NULL;
8612         rsurface.batchvertexmesh_vertexbuffer = NULL;
8613         rsurface.batchvertexmesh_bufferoffset = 0;
8614         rsurface.batchelement3i = NULL;
8615         rsurface.batchelement3i_indexbuffer = NULL;
8616         rsurface.batchelement3i_bufferoffset = 0;
8617         rsurface.batchelement3s = NULL;
8618         rsurface.batchelement3s_indexbuffer = NULL;
8619         rsurface.batchelement3s_bufferoffset = 0;
8620         rsurface.passcolor4f = NULL;
8621         rsurface.passcolor4f_vertexbuffer = NULL;
8622         rsurface.passcolor4f_bufferoffset = 0;
8623         rsurface.forcecurrenttextureupdate = false;
8624 }
8625
8626 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8627 {
8628         dp_model_t *model = ent->model;
8629         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8630         //      return;
8631         rsurface.entity = (entity_render_t *)ent;
8632         rsurface.skeleton = ent->skeleton;
8633         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8634         rsurface.ent_skinnum = ent->skinnum;
8635         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;
8636         rsurface.ent_flags = ent->flags;
8637         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8638         rsurface.matrix = ent->matrix;
8639         rsurface.inversematrix = ent->inversematrix;
8640         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8641         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8642         R_EntityMatrix(&rsurface.matrix);
8643         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8644         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8645         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8646         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8647         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8648         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8649         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8650         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8651         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8652         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8653         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8654         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8655         rsurface.colormod[3] = ent->alpha;
8656         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8657         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8658         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8659         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8660         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8661         if (ent->model->brush.submodel && !prepass)
8662         {
8663                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8664                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8665         }
8666         // if the animcache code decided it should use the shader path, skip the deform step
8667         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8668         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8669         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8670         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8671         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8672         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8673         {
8674                 if (ent->animcache_vertex3f)
8675                 {
8676                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8677                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8678                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8679                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8680                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8681                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8682                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8683                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8684                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8685                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8686                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8687                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8688                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8689                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8690                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8691                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8692                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8693                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8694                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8695                 }
8696                 else if (wanttangents)
8697                 {
8698                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8699                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8700                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8701                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8702                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8703                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8704                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8705                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8706                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8707                         rsurface.modelvertexmesh = NULL;
8708                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8709                         rsurface.modelvertexmesh_bufferoffset = 0;
8710                         rsurface.modelvertex3f_vertexbuffer = NULL;
8711                         rsurface.modelvertex3f_bufferoffset = 0;
8712                         rsurface.modelvertex3f_vertexbuffer = 0;
8713                         rsurface.modelvertex3f_bufferoffset = 0;
8714                         rsurface.modelsvector3f_vertexbuffer = 0;
8715                         rsurface.modelsvector3f_bufferoffset = 0;
8716                         rsurface.modeltvector3f_vertexbuffer = 0;
8717                         rsurface.modeltvector3f_bufferoffset = 0;
8718                         rsurface.modelnormal3f_vertexbuffer = 0;
8719                         rsurface.modelnormal3f_bufferoffset = 0;
8720                 }
8721                 else if (wantnormals)
8722                 {
8723                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8724                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8725                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8726                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8727                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8728                         rsurface.modelsvector3f = NULL;
8729                         rsurface.modeltvector3f = NULL;
8730                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8731                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8732                         rsurface.modelvertexmesh = NULL;
8733                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8734                         rsurface.modelvertexmesh_bufferoffset = 0;
8735                         rsurface.modelvertex3f_vertexbuffer = NULL;
8736                         rsurface.modelvertex3f_bufferoffset = 0;
8737                         rsurface.modelvertex3f_vertexbuffer = 0;
8738                         rsurface.modelvertex3f_bufferoffset = 0;
8739                         rsurface.modelsvector3f_vertexbuffer = 0;
8740                         rsurface.modelsvector3f_bufferoffset = 0;
8741                         rsurface.modeltvector3f_vertexbuffer = 0;
8742                         rsurface.modeltvector3f_bufferoffset = 0;
8743                         rsurface.modelnormal3f_vertexbuffer = 0;
8744                         rsurface.modelnormal3f_bufferoffset = 0;
8745                 }
8746                 else
8747                 {
8748                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8749                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8750                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8751                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8752                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8753                         rsurface.modelsvector3f = NULL;
8754                         rsurface.modeltvector3f = NULL;
8755                         rsurface.modelnormal3f = NULL;
8756                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8757                         rsurface.modelvertexmesh = NULL;
8758                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8759                         rsurface.modelvertexmesh_bufferoffset = 0;
8760                         rsurface.modelvertex3f_vertexbuffer = NULL;
8761                         rsurface.modelvertex3f_bufferoffset = 0;
8762                         rsurface.modelvertex3f_vertexbuffer = 0;
8763                         rsurface.modelvertex3f_bufferoffset = 0;
8764                         rsurface.modelsvector3f_vertexbuffer = 0;
8765                         rsurface.modelsvector3f_bufferoffset = 0;
8766                         rsurface.modeltvector3f_vertexbuffer = 0;
8767                         rsurface.modeltvector3f_bufferoffset = 0;
8768                         rsurface.modelnormal3f_vertexbuffer = 0;
8769                         rsurface.modelnormal3f_bufferoffset = 0;
8770                 }
8771                 rsurface.modelgeneratedvertex = true;
8772         }
8773         else
8774         {
8775                 if (rsurface.entityskeletaltransform3x4)
8776                 {
8777                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8778                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8779                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8780                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8781                 }
8782                 else
8783                 {
8784                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8785                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8786                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8787                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8788                 }
8789                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8790                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8791                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8792                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8793                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8794                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8795                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8796                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8797                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8798                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8799                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8800                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8801                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8802                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8803                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8804                 rsurface.modelgeneratedvertex = false;
8805         }
8806         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8807         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8808         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8809         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8810         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8811         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8812         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8813         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8814         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8815         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8816         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8817         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8818         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8819         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8820         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8821         rsurface.modelelement3i = model->surfmesh.data_element3i;
8822         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8823         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8824         rsurface.modelelement3s = model->surfmesh.data_element3s;
8825         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8826         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8827         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8828         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8829         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8830         rsurface.modelsurfaces = model->data_surfaces;
8831         rsurface.batchgeneratedvertex = false;
8832         rsurface.batchfirstvertex = 0;
8833         rsurface.batchnumvertices = 0;
8834         rsurface.batchfirsttriangle = 0;
8835         rsurface.batchnumtriangles = 0;
8836         rsurface.batchvertex3f  = NULL;
8837         rsurface.batchvertex3f_vertexbuffer = NULL;
8838         rsurface.batchvertex3f_bufferoffset = 0;
8839         rsurface.batchsvector3f = NULL;
8840         rsurface.batchsvector3f_vertexbuffer = NULL;
8841         rsurface.batchsvector3f_bufferoffset = 0;
8842         rsurface.batchtvector3f = NULL;
8843         rsurface.batchtvector3f_vertexbuffer = NULL;
8844         rsurface.batchtvector3f_bufferoffset = 0;
8845         rsurface.batchnormal3f  = NULL;
8846         rsurface.batchnormal3f_vertexbuffer = NULL;
8847         rsurface.batchnormal3f_bufferoffset = 0;
8848         rsurface.batchlightmapcolor4f = NULL;
8849         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8850         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8851         rsurface.batchtexcoordtexture2f = NULL;
8852         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8853         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8854         rsurface.batchtexcoordlightmap2f = NULL;
8855         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8856         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8857         rsurface.batchskeletalindex4ub = NULL;
8858         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8859         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8860         rsurface.batchskeletalweight4ub = NULL;
8861         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8862         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8863         rsurface.batchvertexmesh = NULL;
8864         rsurface.batchvertexmesh_vertexbuffer = NULL;
8865         rsurface.batchvertexmesh_bufferoffset = 0;
8866         rsurface.batchelement3i = NULL;
8867         rsurface.batchelement3i_indexbuffer = NULL;
8868         rsurface.batchelement3i_bufferoffset = 0;
8869         rsurface.batchelement3s = NULL;
8870         rsurface.batchelement3s_indexbuffer = NULL;
8871         rsurface.batchelement3s_bufferoffset = 0;
8872         rsurface.passcolor4f = NULL;
8873         rsurface.passcolor4f_vertexbuffer = NULL;
8874         rsurface.passcolor4f_bufferoffset = 0;
8875         rsurface.forcecurrenttextureupdate = false;
8876 }
8877
8878 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)
8879 {
8880         rsurface.entity = r_refdef.scene.worldentity;
8881         rsurface.skeleton = NULL;
8882         rsurface.ent_skinnum = 0;
8883         rsurface.ent_qwskin = -1;
8884         rsurface.ent_flags = entflags;
8885         rsurface.shadertime = r_refdef.scene.time - shadertime;
8886         rsurface.modelnumvertices = numvertices;
8887         rsurface.modelnumtriangles = numtriangles;
8888         rsurface.matrix = *matrix;
8889         rsurface.inversematrix = *inversematrix;
8890         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8891         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8892         R_EntityMatrix(&rsurface.matrix);
8893         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8894         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8895         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8896         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8897         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8898         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8899         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8900         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8901         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8902         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8903         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8904         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8905         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);
8906         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8907         rsurface.frameblend[0].lerp = 1;
8908         rsurface.ent_alttextures = false;
8909         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8910         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8911         rsurface.entityskeletaltransform3x4 = NULL;
8912         rsurface.entityskeletaltransform3x4buffer = NULL;
8913         rsurface.entityskeletaltransform3x4offset = 0;
8914         rsurface.entityskeletaltransform3x4size = 0;
8915         rsurface.entityskeletalnumtransforms = 0;
8916         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8917         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8918         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8919         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8920         if (wanttangents)
8921         {
8922                 rsurface.modelvertex3f = (float *)vertex3f;
8923                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8924                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8925                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8926         }
8927         else if (wantnormals)
8928         {
8929                 rsurface.modelvertex3f = (float *)vertex3f;
8930                 rsurface.modelsvector3f = NULL;
8931                 rsurface.modeltvector3f = NULL;
8932                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8933         }
8934         else
8935         {
8936                 rsurface.modelvertex3f = (float *)vertex3f;
8937                 rsurface.modelsvector3f = NULL;
8938                 rsurface.modeltvector3f = NULL;
8939                 rsurface.modelnormal3f = NULL;
8940         }
8941         rsurface.modelvertexmesh = NULL;
8942         rsurface.modelvertexmesh_vertexbuffer = NULL;
8943         rsurface.modelvertexmesh_bufferoffset = 0;
8944         rsurface.modelvertex3f_vertexbuffer = 0;
8945         rsurface.modelvertex3f_bufferoffset = 0;
8946         rsurface.modelsvector3f_vertexbuffer = 0;
8947         rsurface.modelsvector3f_bufferoffset = 0;
8948         rsurface.modeltvector3f_vertexbuffer = 0;
8949         rsurface.modeltvector3f_bufferoffset = 0;
8950         rsurface.modelnormal3f_vertexbuffer = 0;
8951         rsurface.modelnormal3f_bufferoffset = 0;
8952         rsurface.modelgeneratedvertex = true;
8953         rsurface.modellightmapcolor4f  = (float *)color4f;
8954         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8955         rsurface.modellightmapcolor4f_bufferoffset = 0;
8956         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8957         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8958         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8959         rsurface.modeltexcoordlightmap2f  = NULL;
8960         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8961         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8962         rsurface.modelskeletalindex4ub = NULL;
8963         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8964         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8965         rsurface.modelskeletalweight4ub = NULL;
8966         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8967         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8968         rsurface.modelelement3i = (int *)element3i;
8969         rsurface.modelelement3i_indexbuffer = NULL;
8970         rsurface.modelelement3i_bufferoffset = 0;
8971         rsurface.modelelement3s = (unsigned short *)element3s;
8972         rsurface.modelelement3s_indexbuffer = NULL;
8973         rsurface.modelelement3s_bufferoffset = 0;
8974         rsurface.modellightmapoffsets = NULL;
8975         rsurface.modelsurfaces = NULL;
8976         rsurface.batchgeneratedvertex = false;
8977         rsurface.batchfirstvertex = 0;
8978         rsurface.batchnumvertices = 0;
8979         rsurface.batchfirsttriangle = 0;
8980         rsurface.batchnumtriangles = 0;
8981         rsurface.batchvertex3f  = NULL;
8982         rsurface.batchvertex3f_vertexbuffer = NULL;
8983         rsurface.batchvertex3f_bufferoffset = 0;
8984         rsurface.batchsvector3f = NULL;
8985         rsurface.batchsvector3f_vertexbuffer = NULL;
8986         rsurface.batchsvector3f_bufferoffset = 0;
8987         rsurface.batchtvector3f = NULL;
8988         rsurface.batchtvector3f_vertexbuffer = NULL;
8989         rsurface.batchtvector3f_bufferoffset = 0;
8990         rsurface.batchnormal3f  = NULL;
8991         rsurface.batchnormal3f_vertexbuffer = NULL;
8992         rsurface.batchnormal3f_bufferoffset = 0;
8993         rsurface.batchlightmapcolor4f = NULL;
8994         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8995         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8996         rsurface.batchtexcoordtexture2f = NULL;
8997         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8998         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8999         rsurface.batchtexcoordlightmap2f = NULL;
9000         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9001         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9002         rsurface.batchskeletalindex4ub = NULL;
9003         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9004         rsurface.batchskeletalindex4ub_bufferoffset = 0;
9005         rsurface.batchskeletalweight4ub = NULL;
9006         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9007         rsurface.batchskeletalweight4ub_bufferoffset = 0;
9008         rsurface.batchvertexmesh = NULL;
9009         rsurface.batchvertexmesh_vertexbuffer = NULL;
9010         rsurface.batchvertexmesh_bufferoffset = 0;
9011         rsurface.batchelement3i = NULL;
9012         rsurface.batchelement3i_indexbuffer = NULL;
9013         rsurface.batchelement3i_bufferoffset = 0;
9014         rsurface.batchelement3s = NULL;
9015         rsurface.batchelement3s_indexbuffer = NULL;
9016         rsurface.batchelement3s_bufferoffset = 0;
9017         rsurface.passcolor4f = NULL;
9018         rsurface.passcolor4f_vertexbuffer = NULL;
9019         rsurface.passcolor4f_bufferoffset = 0;
9020         rsurface.forcecurrenttextureupdate = true;
9021
9022         if (rsurface.modelnumvertices && rsurface.modelelement3i)
9023         {
9024                 if ((wantnormals || wanttangents) && !normal3f)
9025                 {
9026                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9027                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9028                 }
9029                 if (wanttangents && !svector3f)
9030                 {
9031                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9032                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9033                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9034                 }
9035         }
9036 }
9037
9038 float RSurf_FogPoint(const float *v)
9039 {
9040         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9041         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9042         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9043         float FogHeightFade = r_refdef.fogheightfade;
9044         float fogfrac;
9045         unsigned int fogmasktableindex;
9046         if (r_refdef.fogplaneviewabove)
9047                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9048         else
9049                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9050         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9051         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9052 }
9053
9054 float RSurf_FogVertex(const float *v)
9055 {
9056         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9057         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9058         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9059         float FogHeightFade = rsurface.fogheightfade;
9060         float fogfrac;
9061         unsigned int fogmasktableindex;
9062         if (r_refdef.fogplaneviewabove)
9063                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9064         else
9065                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9066         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9067         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9068 }
9069
9070 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9071 {
9072         int i;
9073         for (i = 0;i < numelements;i++)
9074                 outelement3i[i] = inelement3i[i] + adjust;
9075 }
9076
9077 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9078 extern cvar_t gl_vbo;
9079 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9080 {
9081         int deformindex;
9082         int firsttriangle;
9083         int numtriangles;
9084         int firstvertex;
9085         int endvertex;
9086         int numvertices;
9087         int surfacefirsttriangle;
9088         int surfacenumtriangles;
9089         int surfacefirstvertex;
9090         int surfaceendvertex;
9091         int surfacenumvertices;
9092         int batchnumsurfaces = texturenumsurfaces;
9093         int batchnumvertices;
9094         int batchnumtriangles;
9095         int needsupdate;
9096         int i, j;
9097         qboolean gaps;
9098         qboolean dynamicvertex;
9099         float amplitude;
9100         float animpos;
9101         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9102         float waveparms[4];
9103         unsigned char *ub;
9104         q3shaderinfo_deform_t *deform;
9105         const msurface_t *surface, *firstsurface;
9106         r_vertexmesh_t *vertexmesh;
9107         if (!texturenumsurfaces)
9108                 return;
9109         // find vertex range of this surface batch
9110         gaps = false;
9111         firstsurface = texturesurfacelist[0];
9112         firsttriangle = firstsurface->num_firsttriangle;
9113         batchnumvertices = 0;
9114         batchnumtriangles = 0;
9115         firstvertex = endvertex = firstsurface->num_firstvertex;
9116         for (i = 0;i < texturenumsurfaces;i++)
9117         {
9118                 surface = texturesurfacelist[i];
9119                 if (surface != firstsurface + i)
9120                         gaps = true;
9121                 surfacefirstvertex = surface->num_firstvertex;
9122                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9123                 surfacenumvertices = surface->num_vertices;
9124                 surfacenumtriangles = surface->num_triangles;
9125                 if (firstvertex > surfacefirstvertex)
9126                         firstvertex = surfacefirstvertex;
9127                 if (endvertex < surfaceendvertex)
9128                         endvertex = surfaceendvertex;
9129                 batchnumvertices += surfacenumvertices;
9130                 batchnumtriangles += surfacenumtriangles;
9131         }
9132
9133         r_refdef.stats[r_stat_batch_batches]++;
9134         if (gaps)
9135                 r_refdef.stats[r_stat_batch_withgaps]++;
9136         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9137         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9138         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9139
9140         // we now know the vertex range used, and if there are any gaps in it
9141         rsurface.batchfirstvertex = firstvertex;
9142         rsurface.batchnumvertices = endvertex - firstvertex;
9143         rsurface.batchfirsttriangle = firsttriangle;
9144         rsurface.batchnumtriangles = batchnumtriangles;
9145
9146         // this variable holds flags for which properties have been updated that
9147         // may require regenerating vertexmesh array...
9148         needsupdate = 0;
9149
9150         // check if any dynamic vertex processing must occur
9151         dynamicvertex = false;
9152
9153         // a cvar to force the dynamic vertex path to be taken, for debugging
9154         if (r_batch_debugdynamicvertexpath.integer)
9155         {
9156                 if (!dynamicvertex)
9157                 {
9158                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9159                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9160                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9161                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9162                 }
9163                 dynamicvertex = true;
9164         }
9165
9166         // if there is a chance of animated vertex colors, it's a dynamic batch
9167         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9168         {
9169                 if (!dynamicvertex)
9170                 {
9171                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9172                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9173                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9174                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9175                 }
9176                 dynamicvertex = true;
9177                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9178         }
9179
9180         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9181         {
9182                 switch (deform->deform)
9183                 {
9184                 default:
9185                 case Q3DEFORM_PROJECTIONSHADOW:
9186                 case Q3DEFORM_TEXT0:
9187                 case Q3DEFORM_TEXT1:
9188                 case Q3DEFORM_TEXT2:
9189                 case Q3DEFORM_TEXT3:
9190                 case Q3DEFORM_TEXT4:
9191                 case Q3DEFORM_TEXT5:
9192                 case Q3DEFORM_TEXT6:
9193                 case Q3DEFORM_TEXT7:
9194                 case Q3DEFORM_NONE:
9195                         break;
9196                 case Q3DEFORM_AUTOSPRITE:
9197                         if (!dynamicvertex)
9198                         {
9199                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9200                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9201                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9202                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9203                         }
9204                         dynamicvertex = true;
9205                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9206                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9207                         break;
9208                 case Q3DEFORM_AUTOSPRITE2:
9209                         if (!dynamicvertex)
9210                         {
9211                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9212                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9213                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9214                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9215                         }
9216                         dynamicvertex = true;
9217                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9218                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9219                         break;
9220                 case Q3DEFORM_NORMAL:
9221                         if (!dynamicvertex)
9222                         {
9223                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9224                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9225                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9226                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9227                         }
9228                         dynamicvertex = true;
9229                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9230                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9231                         break;
9232                 case Q3DEFORM_WAVE:
9233                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9234                                 break; // if wavefunc is a nop, ignore this transform
9235                         if (!dynamicvertex)
9236                         {
9237                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9238                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9239                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9240                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9241                         }
9242                         dynamicvertex = true;
9243                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9244                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9245                         break;
9246                 case Q3DEFORM_BULGE:
9247                         if (!dynamicvertex)
9248                         {
9249                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9250                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9251                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9252                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9253                         }
9254                         dynamicvertex = true;
9255                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9256                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9257                         break;
9258                 case Q3DEFORM_MOVE:
9259                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9260                                 break; // if wavefunc is a nop, ignore this transform
9261                         if (!dynamicvertex)
9262                         {
9263                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9264                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9265                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9266                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9267                         }
9268                         dynamicvertex = true;
9269                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9270                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9271                         break;
9272                 }
9273         }
9274         if (rsurface.texture->materialshaderpass)
9275         {
9276                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9277                 {
9278                 default:
9279                 case Q3TCGEN_TEXTURE:
9280                         break;
9281                 case Q3TCGEN_LIGHTMAP:
9282                         if (!dynamicvertex)
9283                         {
9284                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9285                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9286                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9287                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9288                         }
9289                         dynamicvertex = true;
9290                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9291                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9292                         break;
9293                 case Q3TCGEN_VECTOR:
9294                         if (!dynamicvertex)
9295                         {
9296                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9297                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9298                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9299                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9300                         }
9301                         dynamicvertex = true;
9302                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9303                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9304                         break;
9305                 case Q3TCGEN_ENVIRONMENT:
9306                         if (!dynamicvertex)
9307                         {
9308                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9309                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9310                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9311                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9312                         }
9313                         dynamicvertex = true;
9314                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9315                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9316                         break;
9317                 }
9318                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9319                 {
9320                         if (!dynamicvertex)
9321                         {
9322                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9323                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9324                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9325                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9326                         }
9327                         dynamicvertex = true;
9328                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9329                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9330                 }
9331         }
9332
9333         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9334         {
9335                 if (!dynamicvertex)
9336                 {
9337                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9338                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9339                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9340                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9341                 }
9342                 dynamicvertex = true;
9343                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9344         }
9345
9346         // when the model data has no vertex buffer (dynamic mesh), we need to
9347         // eliminate gaps
9348         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9349                 batchneed |= BATCHNEED_NOGAPS;
9350
9351         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9352         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9353         // we ensure this by treating the vertex batch as dynamic...
9354         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9355         {
9356                 if (!dynamicvertex)
9357                 {
9358                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9359                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9360                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9361                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9362                 }
9363                 dynamicvertex = true;
9364         }
9365
9366         if (dynamicvertex)
9367         {
9368                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9369                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9370                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9371                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9372                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9373                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9374                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9375                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9376         }
9377
9378         // if needsupdate, we have to do a dynamic vertex batch for sure
9379         if (needsupdate & batchneed)
9380         {
9381                 if (!dynamicvertex)
9382                 {
9383                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9384                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9385                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9386                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9387                 }
9388                 dynamicvertex = true;
9389         }
9390
9391         // see if we need to build vertexmesh from arrays
9392         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9393         {
9394                 if (!dynamicvertex)
9395                 {
9396                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9397                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9398                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9399                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9400                 }
9401                 dynamicvertex = true;
9402         }
9403
9404         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9405         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9406                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9407
9408         rsurface.batchvertex3f = rsurface.modelvertex3f;
9409         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9410         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9411         rsurface.batchsvector3f = rsurface.modelsvector3f;
9412         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9413         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9414         rsurface.batchtvector3f = rsurface.modeltvector3f;
9415         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9416         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9417         rsurface.batchnormal3f = rsurface.modelnormal3f;
9418         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9419         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9420         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9421         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9422         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9423         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9424         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9425         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9426         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9427         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9428         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9429         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9430         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9431         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9432         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9433         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9434         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9435         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9436         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9437         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9438         rsurface.batchelement3i = rsurface.modelelement3i;
9439         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9440         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9441         rsurface.batchelement3s = rsurface.modelelement3s;
9442         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9443         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9444         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9445         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9446         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9447         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9448         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9449
9450         // if any dynamic vertex processing has to occur in software, we copy the
9451         // entire surface list together before processing to rebase the vertices
9452         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9453         //
9454         // if any gaps exist and we do not have a static vertex buffer, we have to
9455         // copy the surface list together to avoid wasting upload bandwidth on the
9456         // vertices in the gaps.
9457         //
9458         // if gaps exist and we have a static vertex buffer, we can choose whether
9459         // to combine the index buffer ranges into one dynamic index buffer or
9460         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9461         //
9462         // in many cases the batch is reduced to one draw call.
9463
9464         rsurface.batchmultidraw = false;
9465         rsurface.batchmultidrawnumsurfaces = 0;
9466         rsurface.batchmultidrawsurfacelist = NULL;
9467
9468         if (!dynamicvertex)
9469         {
9470                 // static vertex data, just set pointers...
9471                 rsurface.batchgeneratedvertex = false;
9472                 // if there are gaps, we want to build a combined index buffer,
9473                 // otherwise use the original static buffer with an appropriate offset
9474                 if (gaps)
9475                 {
9476                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9477                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9478                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9479                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9480                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9481                         {
9482                                 rsurface.batchmultidraw = true;
9483                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9484                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9485                                 return;
9486                         }
9487                         // build a new triangle elements array for this batch
9488                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9489                         rsurface.batchfirsttriangle = 0;
9490                         numtriangles = 0;
9491                         for (i = 0;i < texturenumsurfaces;i++)
9492                         {
9493                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9494                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9495                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9496                                 numtriangles += surfacenumtriangles;
9497                         }
9498                         rsurface.batchelement3i_indexbuffer = NULL;
9499                         rsurface.batchelement3i_bufferoffset = 0;
9500                         rsurface.batchelement3s = NULL;
9501                         rsurface.batchelement3s_indexbuffer = NULL;
9502                         rsurface.batchelement3s_bufferoffset = 0;
9503                         if (endvertex <= 65536)
9504                         {
9505                                 // make a 16bit (unsigned short) index array if possible
9506                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9507                                 for (i = 0;i < numtriangles*3;i++)
9508                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9509                         }
9510                         // upload buffer data for the copytriangles batch
9511                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9512                         {
9513                                 if (rsurface.batchelement3s)
9514                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9515                                 else if (rsurface.batchelement3i)
9516                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9517                         }
9518                 }
9519                 else
9520                 {
9521                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9522                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9523                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9524                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9525                 }
9526                 return;
9527         }
9528
9529         // something needs software processing, do it for real...
9530         // we only directly handle separate array data in this case and then
9531         // generate interleaved data if needed...
9532         rsurface.batchgeneratedvertex = true;
9533         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9534         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9535         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9536         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9537
9538         // now copy the vertex data into a combined array and make an index array
9539         // (this is what Quake3 does all the time)
9540         // we also apply any skeletal animation here that would have been done in
9541         // the vertex shader, because most of the dynamic vertex animation cases
9542         // need actual vertex positions and normals
9543         //if (dynamicvertex)
9544         {
9545                 rsurface.batchvertexmesh = NULL;
9546                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9547                 rsurface.batchvertexmesh_bufferoffset = 0;
9548                 rsurface.batchvertex3f = NULL;
9549                 rsurface.batchvertex3f_vertexbuffer = NULL;
9550                 rsurface.batchvertex3f_bufferoffset = 0;
9551                 rsurface.batchsvector3f = NULL;
9552                 rsurface.batchsvector3f_vertexbuffer = NULL;
9553                 rsurface.batchsvector3f_bufferoffset = 0;
9554                 rsurface.batchtvector3f = NULL;
9555                 rsurface.batchtvector3f_vertexbuffer = NULL;
9556                 rsurface.batchtvector3f_bufferoffset = 0;
9557                 rsurface.batchnormal3f = NULL;
9558                 rsurface.batchnormal3f_vertexbuffer = NULL;
9559                 rsurface.batchnormal3f_bufferoffset = 0;
9560                 rsurface.batchlightmapcolor4f = NULL;
9561                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9562                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9563                 rsurface.batchtexcoordtexture2f = NULL;
9564                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9565                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9566                 rsurface.batchtexcoordlightmap2f = NULL;
9567                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9568                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9569                 rsurface.batchskeletalindex4ub = NULL;
9570                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9571                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9572                 rsurface.batchskeletalweight4ub = NULL;
9573                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9574                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9575                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9576                 rsurface.batchelement3i_indexbuffer = NULL;
9577                 rsurface.batchelement3i_bufferoffset = 0;
9578                 rsurface.batchelement3s = NULL;
9579                 rsurface.batchelement3s_indexbuffer = NULL;
9580                 rsurface.batchelement3s_bufferoffset = 0;
9581                 rsurface.batchskeletaltransform3x4buffer = NULL;
9582                 rsurface.batchskeletaltransform3x4offset = 0;
9583                 rsurface.batchskeletaltransform3x4size = 0;
9584                 // we'll only be setting up certain arrays as needed
9585                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9586                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9587                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9588                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9589                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9590                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9591                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9592                 {
9593                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9594                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9595                 }
9596                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9597                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9598                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9599                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9600                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9601                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9602                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9603                 {
9604                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9605                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9606                 }
9607                 numvertices = 0;
9608                 numtriangles = 0;
9609                 for (i = 0;i < texturenumsurfaces;i++)
9610                 {
9611                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9612                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9613                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9614                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9615                         // copy only the data requested
9616                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9617                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9618                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9619                         {
9620                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9621                                 {
9622                                         if (rsurface.batchvertex3f)
9623                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9624                                         else
9625                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9626                                 }
9627                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9628                                 {
9629                                         if (rsurface.modelnormal3f)
9630                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9631                                         else
9632                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9633                                 }
9634                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9635                                 {
9636                                         if (rsurface.modelsvector3f)
9637                                         {
9638                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9639                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9640                                         }
9641                                         else
9642                                         {
9643                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9644                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9645                                         }
9646                                 }
9647                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9648                                 {
9649                                         if (rsurface.modellightmapcolor4f)
9650                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9651                                         else
9652                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9653                                 }
9654                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9655                                 {
9656                                         if (rsurface.modeltexcoordtexture2f)
9657                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9658                                         else
9659                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9660                                 }
9661                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9662                                 {
9663                                         if (rsurface.modeltexcoordlightmap2f)
9664                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9665                                         else
9666                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9667                                 }
9668                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9669                                 {
9670                                         if (rsurface.modelskeletalindex4ub)
9671                                         {
9672                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9673                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9674                                         }
9675                                         else
9676                                         {
9677                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9678                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9679                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9680                                                 for (j = 0;j < surfacenumvertices;j++)
9681                                                         ub[j*4] = 255;
9682                                         }
9683                                 }
9684                         }
9685                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9686                         numvertices += surfacenumvertices;
9687                         numtriangles += surfacenumtriangles;
9688                 }
9689
9690                 // generate a 16bit index array as well if possible
9691                 // (in general, dynamic batches fit)
9692                 if (numvertices <= 65536)
9693                 {
9694                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9695                         for (i = 0;i < numtriangles*3;i++)
9696                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9697                 }
9698
9699                 // since we've copied everything, the batch now starts at 0
9700                 rsurface.batchfirstvertex = 0;
9701                 rsurface.batchnumvertices = batchnumvertices;
9702                 rsurface.batchfirsttriangle = 0;
9703                 rsurface.batchnumtriangles = batchnumtriangles;
9704         }
9705
9706         // apply skeletal animation that would have been done in the vertex shader
9707         if (rsurface.batchskeletaltransform3x4)
9708         {
9709                 const unsigned char *si;
9710                 const unsigned char *sw;
9711                 const float *t[4];
9712                 const float *b = rsurface.batchskeletaltransform3x4;
9713                 float *vp, *vs, *vt, *vn;
9714                 float w[4];
9715                 float m[3][4], n[3][4];
9716                 float tp[3], ts[3], tt[3], tn[3];
9717                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9718                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9719                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9720                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9721                 si = rsurface.batchskeletalindex4ub;
9722                 sw = rsurface.batchskeletalweight4ub;
9723                 vp = rsurface.batchvertex3f;
9724                 vs = rsurface.batchsvector3f;
9725                 vt = rsurface.batchtvector3f;
9726                 vn = rsurface.batchnormal3f;
9727                 memset(m[0], 0, sizeof(m));
9728                 memset(n[0], 0, sizeof(n));
9729                 for (i = 0;i < batchnumvertices;i++)
9730                 {
9731                         t[0] = b + si[0]*12;
9732                         if (sw[0] == 255)
9733                         {
9734                                 // common case - only one matrix
9735                                 m[0][0] = t[0][ 0];
9736                                 m[0][1] = t[0][ 1];
9737                                 m[0][2] = t[0][ 2];
9738                                 m[0][3] = t[0][ 3];
9739                                 m[1][0] = t[0][ 4];
9740                                 m[1][1] = t[0][ 5];
9741                                 m[1][2] = t[0][ 6];
9742                                 m[1][3] = t[0][ 7];
9743                                 m[2][0] = t[0][ 8];
9744                                 m[2][1] = t[0][ 9];
9745                                 m[2][2] = t[0][10];
9746                                 m[2][3] = t[0][11];
9747                         }
9748                         else if (sw[2] + sw[3])
9749                         {
9750                                 // blend 4 matrices
9751                                 t[1] = b + si[1]*12;
9752                                 t[2] = b + si[2]*12;
9753                                 t[3] = b + si[3]*12;
9754                                 w[0] = sw[0] * (1.0f / 255.0f);
9755                                 w[1] = sw[1] * (1.0f / 255.0f);
9756                                 w[2] = sw[2] * (1.0f / 255.0f);
9757                                 w[3] = sw[3] * (1.0f / 255.0f);
9758                                 // blend the matrices
9759                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9760                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9761                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9762                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9763                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9764                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9765                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9766                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9767                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9768                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9769                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9770                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9771                         }
9772                         else
9773                         {
9774                                 // blend 2 matrices
9775                                 t[1] = b + si[1]*12;
9776                                 w[0] = sw[0] * (1.0f / 255.0f);
9777                                 w[1] = sw[1] * (1.0f / 255.0f);
9778                                 // blend the matrices
9779                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9780                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9781                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9782                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9783                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9784                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9785                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9786                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9787                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9788                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9789                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9790                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9791                         }
9792                         si += 4;
9793                         sw += 4;
9794                         // modify the vertex
9795                         VectorCopy(vp, tp);
9796                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9797                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9798                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9799                         vp += 3;
9800                         if (vn)
9801                         {
9802                                 // the normal transformation matrix is a set of cross products...
9803                                 CrossProduct(m[1], m[2], n[0]);
9804                                 CrossProduct(m[2], m[0], n[1]);
9805                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9806                                 VectorCopy(vn, tn);
9807                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9808                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9809                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9810                                 VectorNormalize(vn);
9811                                 vn += 3;
9812                                 if (vs)
9813                                 {
9814                                         VectorCopy(vs, ts);
9815                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9816                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9817                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9818                                         VectorNormalize(vs);
9819                                         vs += 3;
9820                                         VectorCopy(vt, tt);
9821                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9822                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9823                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9824                                         VectorNormalize(vt);
9825                                         vt += 3;
9826                                 }
9827                         }
9828                 }
9829                 rsurface.batchskeletaltransform3x4 = NULL;
9830                 rsurface.batchskeletalnumtransforms = 0;
9831         }
9832
9833         // q1bsp surfaces rendered in vertex color mode have to have colors
9834         // calculated based on lightstyles
9835         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9836         {
9837                 // generate color arrays for the surfaces in this list
9838                 int c[4];
9839                 int scale;
9840                 int size3;
9841                 const int *offsets;
9842                 const unsigned char *lm;
9843                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9844                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9845                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9846                 numvertices = 0;
9847                 for (i = 0;i < texturenumsurfaces;i++)
9848                 {
9849                         surface = texturesurfacelist[i];
9850                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9851                         surfacenumvertices = surface->num_vertices;
9852                         if (surface->lightmapinfo->samples)
9853                         {
9854                                 for (j = 0;j < surfacenumvertices;j++)
9855                                 {
9856                                         lm = surface->lightmapinfo->samples + offsets[j];
9857                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9858                                         VectorScale(lm, scale, c);
9859                                         if (surface->lightmapinfo->styles[1] != 255)
9860                                         {
9861                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9862                                                 lm += size3;
9863                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9864                                                 VectorMA(c, scale, lm, c);
9865                                                 if (surface->lightmapinfo->styles[2] != 255)
9866                                                 {
9867                                                         lm += size3;
9868                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9869                                                         VectorMA(c, scale, lm, c);
9870                                                         if (surface->lightmapinfo->styles[3] != 255)
9871                                                         {
9872                                                                 lm += size3;
9873                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9874                                                                 VectorMA(c, scale, lm, c);
9875                                                         }
9876                                                 }
9877                                         }
9878                                         c[0] >>= 7;
9879                                         c[1] >>= 7;
9880                                         c[2] >>= 7;
9881                                         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);
9882                                         numvertices++;
9883                                 }
9884                         }
9885                         else
9886                         {
9887                                 for (j = 0;j < surfacenumvertices;j++)
9888                                 {
9889                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9890                                         numvertices++;
9891                                 }
9892                         }
9893                 }
9894         }
9895
9896         // if vertices are deformed (sprite flares and things in maps, possibly
9897         // water waves, bulges and other deformations), modify the copied vertices
9898         // in place
9899         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9900         {
9901                 float scale;
9902                 switch (deform->deform)
9903                 {
9904                 default:
9905                 case Q3DEFORM_PROJECTIONSHADOW:
9906                 case Q3DEFORM_TEXT0:
9907                 case Q3DEFORM_TEXT1:
9908                 case Q3DEFORM_TEXT2:
9909                 case Q3DEFORM_TEXT3:
9910                 case Q3DEFORM_TEXT4:
9911                 case Q3DEFORM_TEXT5:
9912                 case Q3DEFORM_TEXT6:
9913                 case Q3DEFORM_TEXT7:
9914                 case Q3DEFORM_NONE:
9915                         break;
9916                 case Q3DEFORM_AUTOSPRITE:
9917                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9918                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9919                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9920                         VectorNormalize(newforward);
9921                         VectorNormalize(newright);
9922                         VectorNormalize(newup);
9923 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9924 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9925 //                      rsurface.batchvertex3f_bufferoffset = 0;
9926 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9927 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9928 //                      rsurface.batchsvector3f_bufferoffset = 0;
9929 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9930 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9931 //                      rsurface.batchtvector3f_bufferoffset = 0;
9932 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9933 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9934 //                      rsurface.batchnormal3f_bufferoffset = 0;
9935                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9936                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9937                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9938                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9939                                 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);
9940                         // a single autosprite surface can contain multiple sprites...
9941                         for (j = 0;j < batchnumvertices - 3;j += 4)
9942                         {
9943                                 VectorClear(center);
9944                                 for (i = 0;i < 4;i++)
9945                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9946                                 VectorScale(center, 0.25f, center);
9947                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9948                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9949                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9950                                 for (i = 0;i < 4;i++)
9951                                 {
9952                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9953                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9954                                 }
9955                         }
9956                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9957                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9958                         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);
9959                         break;
9960                 case Q3DEFORM_AUTOSPRITE2:
9961                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9962                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9963                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9964                         VectorNormalize(newforward);
9965                         VectorNormalize(newright);
9966                         VectorNormalize(newup);
9967 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9968 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9969 //                      rsurface.batchvertex3f_bufferoffset = 0;
9970                         {
9971                                 const float *v1, *v2;
9972                                 vec3_t start, end;
9973                                 float f, l;
9974                                 struct
9975                                 {
9976                                         float length2;
9977                                         const float *v1;
9978                                         const float *v2;
9979                                 }
9980                                 shortest[2];
9981                                 memset(shortest, 0, sizeof(shortest));
9982                                 // a single autosprite surface can contain multiple sprites...
9983                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9984                                 {
9985                                         VectorClear(center);
9986                                         for (i = 0;i < 4;i++)
9987                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9988                                         VectorScale(center, 0.25f, center);
9989                                         // find the two shortest edges, then use them to define the
9990                                         // axis vectors for rotating around the central axis
9991                                         for (i = 0;i < 6;i++)
9992                                         {
9993                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9994                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9995                                                 l = VectorDistance2(v1, v2);
9996                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9997                                                 if (v1[2] != v2[2])
9998                                                         l += (1.0f / 1024.0f);
9999                                                 if (shortest[0].length2 > l || i == 0)
10000                                                 {
10001                                                         shortest[1] = shortest[0];
10002                                                         shortest[0].length2 = l;
10003                                                         shortest[0].v1 = v1;
10004                                                         shortest[0].v2 = v2;
10005                                                 }
10006                                                 else if (shortest[1].length2 > l || i == 1)
10007                                                 {
10008                                                         shortest[1].length2 = l;
10009                                                         shortest[1].v1 = v1;
10010                                                         shortest[1].v2 = v2;
10011                                                 }
10012                                         }
10013                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10014                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10015                                         // this calculates the right vector from the shortest edge
10016                                         // and the up vector from the edge midpoints
10017                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10018                                         VectorNormalize(right);
10019                                         VectorSubtract(end, start, up);
10020                                         VectorNormalize(up);
10021                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10022                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10023                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10024                                         VectorNegate(forward, forward);
10025                                         VectorReflect(forward, 0, up, forward);
10026                                         VectorNormalize(forward);
10027                                         CrossProduct(up, forward, newright);
10028                                         VectorNormalize(newright);
10029                                         // rotate the quad around the up axis vector, this is made
10030                                         // especially easy by the fact we know the quad is flat,
10031                                         // so we only have to subtract the center position and
10032                                         // measure distance along the right vector, and then
10033                                         // multiply that by the newright vector and add back the
10034                                         // center position
10035                                         // we also need to subtract the old position to undo the
10036                                         // displacement from the center, which we do with a
10037                                         // DotProduct, the subtraction/addition of center is also
10038                                         // optimized into DotProducts here
10039                                         l = DotProduct(right, center);
10040                                         for (i = 0;i < 4;i++)
10041                                         {
10042                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10043                                                 f = DotProduct(right, v1) - l;
10044                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10045                                         }
10046                                 }
10047                         }
10048                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10049                         {
10050 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10051 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10052 //                              rsurface.batchnormal3f_bufferoffset = 0;
10053                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10054                         }
10055                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10056                         {
10057 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10058 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10059 //                              rsurface.batchsvector3f_bufferoffset = 0;
10060 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10061 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10062 //                              rsurface.batchtvector3f_bufferoffset = 0;
10063                                 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);
10064                         }
10065                         break;
10066                 case Q3DEFORM_NORMAL:
10067                         // deform the normals to make reflections wavey
10068                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10069                         rsurface.batchnormal3f_vertexbuffer = NULL;
10070                         rsurface.batchnormal3f_bufferoffset = 0;
10071                         for (j = 0;j < batchnumvertices;j++)
10072                         {
10073                                 float vertex[3];
10074                                 float *normal = rsurface.batchnormal3f + 3*j;
10075                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10076                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10077                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10078                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10079                                 VectorNormalize(normal);
10080                         }
10081                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10082                         {
10083 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10084 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10085 //                              rsurface.batchsvector3f_bufferoffset = 0;
10086 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10087 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10088 //                              rsurface.batchtvector3f_bufferoffset = 0;
10089                                 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);
10090                         }
10091                         break;
10092                 case Q3DEFORM_WAVE:
10093                         // deform vertex array to make wavey water and flags and such
10094                         waveparms[0] = deform->waveparms[0];
10095                         waveparms[1] = deform->waveparms[1];
10096                         waveparms[2] = deform->waveparms[2];
10097                         waveparms[3] = deform->waveparms[3];
10098                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10099                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10100                         // this is how a divisor of vertex influence on deformation
10101                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10102                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10103 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10104 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10105 //                      rsurface.batchvertex3f_bufferoffset = 0;
10106 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10107 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10108 //                      rsurface.batchnormal3f_bufferoffset = 0;
10109                         for (j = 0;j < batchnumvertices;j++)
10110                         {
10111                                 // if the wavefunc depends on time, evaluate it per-vertex
10112                                 if (waveparms[3])
10113                                 {
10114                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10115                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10116                                 }
10117                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10118                         }
10119                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10120                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10121                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10122                         {
10123 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10124 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10125 //                              rsurface.batchsvector3f_bufferoffset = 0;
10126 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10127 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10128 //                              rsurface.batchtvector3f_bufferoffset = 0;
10129                                 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);
10130                         }
10131                         break;
10132                 case Q3DEFORM_BULGE:
10133                         // deform vertex array to make the surface have moving bulges
10134 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10135 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10136 //                      rsurface.batchvertex3f_bufferoffset = 0;
10137 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10138 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10139 //                      rsurface.batchnormal3f_bufferoffset = 0;
10140                         for (j = 0;j < batchnumvertices;j++)
10141                         {
10142                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10143                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10144                         }
10145                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10146                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10147                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10148                         {
10149 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10150 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10151 //                              rsurface.batchsvector3f_bufferoffset = 0;
10152 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10153 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10154 //                              rsurface.batchtvector3f_bufferoffset = 0;
10155                                 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);
10156                         }
10157                         break;
10158                 case Q3DEFORM_MOVE:
10159                         // deform vertex array
10160                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10161                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10162                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10163                         VectorScale(deform->parms, scale, waveparms);
10164 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10165 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10166 //                      rsurface.batchvertex3f_bufferoffset = 0;
10167                         for (j = 0;j < batchnumvertices;j++)
10168                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10169                         break;
10170                 }
10171         }
10172
10173         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10174         {
10175         // generate texcoords based on the chosen texcoord source
10176                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10177                 {
10178                 default:
10179                 case Q3TCGEN_TEXTURE:
10180                         break;
10181                 case Q3TCGEN_LIGHTMAP:
10182         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10183         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10184         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10185                         if (rsurface.batchtexcoordlightmap2f)
10186                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10187                         break;
10188                 case Q3TCGEN_VECTOR:
10189         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10190         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10191         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10192                         for (j = 0;j < batchnumvertices;j++)
10193                         {
10194                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10195                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10196                         }
10197                         break;
10198                 case Q3TCGEN_ENVIRONMENT:
10199                         // make environment reflections using a spheremap
10200                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10201                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10202                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10203                         for (j = 0;j < batchnumvertices;j++)
10204                         {
10205                                 // identical to Q3A's method, but executed in worldspace so
10206                                 // carried models can be shiny too
10207
10208                                 float viewer[3], d, reflected[3], worldreflected[3];
10209
10210                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10211                                 // VectorNormalize(viewer);
10212
10213                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10214
10215                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10216                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10217                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10218                                 // note: this is proportinal to viewer, so we can normalize later
10219
10220                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10221                                 VectorNormalize(worldreflected);
10222
10223                                 // note: this sphere map only uses world x and z!
10224                                 // so positive and negative y will LOOK THE SAME.
10225                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10226                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10227                         }
10228                         break;
10229                 }
10230                 // the only tcmod that needs software vertex processing is turbulent, so
10231                 // check for it here and apply the changes if needed
10232                 // and we only support that as the first one
10233                 // (handling a mixture of turbulent and other tcmods would be problematic
10234                 //  without punting it entirely to a software path)
10235                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10236                 {
10237                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10238                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10239         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10240         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10241         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10242                         for (j = 0;j < batchnumvertices;j++)
10243                         {
10244                                 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);
10245                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10246                         }
10247                 }
10248         }
10249
10250         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10251         {
10252                 // convert the modified arrays to vertex structs
10253 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10254 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10255 //              rsurface.batchvertexmesh_bufferoffset = 0;
10256                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10257                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10258                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10259                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10260                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10261                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10262                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10263                 {
10264                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10265                         {
10266                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10267                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10268                         }
10269                 }
10270                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10271                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10272                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10273                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10274                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10275                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10276                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10277                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10278                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10279                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10280                 {
10281                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10282                         {
10283                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10284                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10285                         }
10286                 }
10287         }
10288
10289         // upload buffer data for the dynamic batch
10290         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10291         {
10292                 if (rsurface.batchvertexmesh)
10293                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10294                 else
10295                 {
10296                         if (rsurface.batchvertex3f)
10297                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10298                         if (rsurface.batchsvector3f)
10299                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10300                         if (rsurface.batchtvector3f)
10301                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10302                         if (rsurface.batchnormal3f)
10303                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10304                         if (rsurface.batchlightmapcolor4f)
10305                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10306                         if (rsurface.batchtexcoordtexture2f)
10307                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10308                         if (rsurface.batchtexcoordlightmap2f)
10309                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10310                         if (rsurface.batchskeletalindex4ub)
10311                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10312                         if (rsurface.batchskeletalweight4ub)
10313                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10314                 }
10315                 if (rsurface.batchelement3s)
10316                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10317                 else if (rsurface.batchelement3i)
10318                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10319         }
10320 }
10321
10322 void RSurf_DrawBatch(void)
10323 {
10324         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10325         // through the pipeline, killing it earlier in the pipeline would have
10326         // per-surface overhead rather than per-batch overhead, so it's best to
10327         // reject it here, before it hits glDraw.
10328         if (rsurface.batchnumtriangles == 0)
10329                 return;
10330 #if 0
10331         // batch debugging code
10332         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10333         {
10334                 int i;
10335                 int j;
10336                 int c;
10337                 const int *e;
10338                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10339                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10340                 {
10341                         c = e[i];
10342                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10343                         {
10344                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10345                                 {
10346                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10347                                                 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);
10348                                         break;
10349                                 }
10350                         }
10351                 }
10352         }
10353 #endif
10354         if (rsurface.batchmultidraw)
10355         {
10356                 // issue multiple draws rather than copying index data
10357                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10358                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10359                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10360                 for (i = 0;i < numsurfaces;)
10361                 {
10362                         // combine consecutive surfaces as one draw
10363                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10364                                 if (surfacelist[j] != surfacelist[k] + 1)
10365                                         break;
10366                         firstvertex = surfacelist[i]->num_firstvertex;
10367                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10368                         firsttriangle = surfacelist[i]->num_firsttriangle;
10369                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10370                         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);
10371                         i = j;
10372                 }
10373         }
10374         else
10375         {
10376                 // there is only one consecutive run of index data (may have been combined)
10377                 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);
10378         }
10379 }
10380
10381 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10382 {
10383         // pick the closest matching water plane
10384         int planeindex, vertexindex, bestplaneindex = -1;
10385         float d, bestd;
10386         vec3_t vert;
10387         const float *v;
10388         r_waterstate_waterplane_t *p;
10389         qboolean prepared = false;
10390         bestd = 0;
10391         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10392         {
10393                 if(p->camera_entity != rsurface.texture->camera_entity)
10394                         continue;
10395                 d = 0;
10396                 if(!prepared)
10397                 {
10398                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10399                         prepared = true;
10400                         if(rsurface.batchnumvertices == 0)
10401                                 break;
10402                 }
10403                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10404                 {
10405                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10406                         d += fabs(PlaneDiff(vert, &p->plane));
10407                 }
10408                 if (bestd > d || bestplaneindex < 0)
10409                 {
10410                         bestd = d;
10411                         bestplaneindex = planeindex;
10412                 }
10413         }
10414         return bestplaneindex;
10415         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10416         // this situation though, as it might be better to render single larger
10417         // batches with useless stuff (backface culled for example) than to
10418         // render multiple smaller batches
10419 }
10420
10421 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10422 {
10423         int i;
10424         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10425         rsurface.passcolor4f_vertexbuffer = 0;
10426         rsurface.passcolor4f_bufferoffset = 0;
10427         for (i = 0;i < rsurface.batchnumvertices;i++)
10428                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10429 }
10430
10431 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10432 {
10433         int i;
10434         float f;
10435         const float *v;
10436         const float *c;
10437         float *c2;
10438         if (rsurface.passcolor4f)
10439         {
10440                 // generate color arrays
10441                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10442                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10443                 rsurface.passcolor4f_vertexbuffer = 0;
10444                 rsurface.passcolor4f_bufferoffset = 0;
10445                 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)
10446                 {
10447                         f = RSurf_FogVertex(v);
10448                         c2[0] = c[0] * f;
10449                         c2[1] = c[1] * f;
10450                         c2[2] = c[2] * f;
10451                         c2[3] = c[3];
10452                 }
10453         }
10454         else
10455         {
10456                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10457                 rsurface.passcolor4f_vertexbuffer = 0;
10458                 rsurface.passcolor4f_bufferoffset = 0;
10459                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10460                 {
10461                         f = RSurf_FogVertex(v);
10462                         c2[0] = f;
10463                         c2[1] = f;
10464                         c2[2] = f;
10465                         c2[3] = 1;
10466                 }
10467         }
10468 }
10469
10470 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10471 {
10472         int i;
10473         float f;
10474         const float *v;
10475         const float *c;
10476         float *c2;
10477         if (!rsurface.passcolor4f)
10478                 return;
10479         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10480         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10481         rsurface.passcolor4f_vertexbuffer = 0;
10482         rsurface.passcolor4f_bufferoffset = 0;
10483         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)
10484         {
10485                 f = RSurf_FogVertex(v);
10486                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10487                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10488                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10489                 c2[3] = c[3];
10490         }
10491 }
10492
10493 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10494 {
10495         int i;
10496         const float *c;
10497         float *c2;
10498         if (!rsurface.passcolor4f)
10499                 return;
10500         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10501         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10502         rsurface.passcolor4f_vertexbuffer = 0;
10503         rsurface.passcolor4f_bufferoffset = 0;
10504         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10505         {
10506                 c2[0] = c[0] * r;
10507                 c2[1] = c[1] * g;
10508                 c2[2] = c[2] * b;
10509                 c2[3] = c[3] * a;
10510         }
10511 }
10512
10513 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10514 {
10515         int i;
10516         const float *c;
10517         float *c2;
10518         if (!rsurface.passcolor4f)
10519                 return;
10520         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10521         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10522         rsurface.passcolor4f_vertexbuffer = 0;
10523         rsurface.passcolor4f_bufferoffset = 0;
10524         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10525         {
10526                 c2[0] = c[0] + r_refdef.scene.ambient;
10527                 c2[1] = c[1] + r_refdef.scene.ambient;
10528                 c2[2] = c[2] + r_refdef.scene.ambient;
10529                 c2[3] = c[3];
10530         }
10531 }
10532
10533 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10534 {
10535         // TODO: optimize
10536         rsurface.passcolor4f = NULL;
10537         rsurface.passcolor4f_vertexbuffer = 0;
10538         rsurface.passcolor4f_bufferoffset = 0;
10539         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10540         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10541         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10542         GL_Color(r, g, b, a);
10543         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10544         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10545         R_Mesh_TexMatrix(0, NULL);
10546         RSurf_DrawBatch();
10547 }
10548
10549 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10550 {
10551         // TODO: optimize applyfog && applycolor case
10552         // just apply fog if necessary, and tint the fog color array if necessary
10553         rsurface.passcolor4f = NULL;
10554         rsurface.passcolor4f_vertexbuffer = 0;
10555         rsurface.passcolor4f_bufferoffset = 0;
10556         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10557         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10558         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10559         GL_Color(r, g, b, a);
10560         RSurf_DrawBatch();
10561 }
10562
10563 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10564 {
10565         // TODO: optimize
10566         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10567         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10568         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10569         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10570         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10571         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10572         GL_Color(r, g, b, a);
10573         RSurf_DrawBatch();
10574 }
10575
10576 static void RSurf_DrawBatch_GL11_ClampColor(void)
10577 {
10578         int i;
10579         const float *c1;
10580         float *c2;
10581         if (!rsurface.passcolor4f)
10582                 return;
10583         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10584         {
10585                 c2[0] = bound(0.0f, c1[0], 1.0f);
10586                 c2[1] = bound(0.0f, c1[1], 1.0f);
10587                 c2[2] = bound(0.0f, c1[2], 1.0f);
10588                 c2[3] = bound(0.0f, c1[3], 1.0f);
10589         }
10590 }
10591
10592 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10593 {
10594         int i;
10595         float f;
10596         const float *v;
10597         const float *n;
10598         float *c;
10599         //vec3_t eyedir;
10600
10601         // fake shading
10602         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10603         rsurface.passcolor4f_vertexbuffer = 0;
10604         rsurface.passcolor4f_bufferoffset = 0;
10605         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
10606         {
10607                 f = -DotProduct(r_refdef.view.forward, n);
10608                 f = max(0, f);
10609                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10610                 f *= r_refdef.lightmapintensity;
10611                 Vector4Set(c, f, f, f, 1);
10612         }
10613 }
10614
10615 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10616 {
10617         RSurf_DrawBatch_GL11_ApplyFakeLight();
10618         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10619         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10620         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10621         GL_Color(r, g, b, a);
10622         RSurf_DrawBatch();
10623 }
10624
10625 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10626 {
10627         int i;
10628         float f;
10629         float alpha;
10630         const float *v;
10631         const float *n;
10632         float *c;
10633         vec3_t ambientcolor;
10634         vec3_t diffusecolor;
10635         vec3_t lightdir;
10636         // TODO: optimize
10637         // model lighting
10638         VectorCopy(rsurface.modellight_lightdir, lightdir);
10639         f = 0.5f * r_refdef.lightmapintensity;
10640         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10641         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10642         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10643         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10644         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10645         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10646         alpha = *a;
10647         if (VectorLength2(diffusecolor) > 0)
10648         {
10649                 // q3-style directional shading
10650                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10651                 rsurface.passcolor4f_vertexbuffer = 0;
10652                 rsurface.passcolor4f_bufferoffset = 0;
10653                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
10654                 {
10655                         if ((f = DotProduct(n, lightdir)) > 0)
10656                                 VectorMA(ambientcolor, f, diffusecolor, c);
10657                         else
10658                                 VectorCopy(ambientcolor, c);
10659                         c[3] = alpha;
10660                 }
10661                 *r = 1;
10662                 *g = 1;
10663                 *b = 1;
10664                 *a = 1;
10665                 *applycolor = false;
10666         }
10667         else
10668         {
10669                 *r = ambientcolor[0];
10670                 *g = ambientcolor[1];
10671                 *b = ambientcolor[2];
10672                 rsurface.passcolor4f = NULL;
10673                 rsurface.passcolor4f_vertexbuffer = 0;
10674                 rsurface.passcolor4f_bufferoffset = 0;
10675         }
10676 }
10677
10678 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10679 {
10680         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10681         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10682         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10683         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10684         GL_Color(r, g, b, a);
10685         RSurf_DrawBatch();
10686 }
10687
10688 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10689 {
10690         int i;
10691         float f;
10692         const float *v;
10693         float *c;
10694
10695         // fake shading
10696         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10697         rsurface.passcolor4f_vertexbuffer = 0;
10698         rsurface.passcolor4f_bufferoffset = 0;
10699
10700         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10701         {
10702                 f = 1 - RSurf_FogVertex(v);
10703                 c[0] = r;
10704                 c[1] = g;
10705                 c[2] = b;
10706                 c[3] = f * a;
10707         }
10708 }
10709
10710 void RSurf_SetupDepthAndCulling(void)
10711 {
10712         // submodels are biased to avoid z-fighting with world surfaces that they
10713         // may be exactly overlapping (avoids z-fighting artifacts on certain
10714         // doors and things in Quake maps)
10715         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10716         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10717         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10718         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10719 }
10720
10721 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10722 {
10723         // transparent sky would be ridiculous
10724         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10725                 return;
10726         R_SetupShader_Generic_NoTexture(false, false);
10727         skyrenderlater = true;
10728         RSurf_SetupDepthAndCulling();
10729         GL_DepthMask(true);
10730         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10731         // skymasking on them, and Quake3 never did sky masking (unlike
10732         // software Quake and software Quake2), so disable the sky masking
10733         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10734         // and skymasking also looks very bad when noclipping outside the
10735         // level, so don't use it then either.
10736         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10737         {
10738                 R_Mesh_ResetTextureState();
10739                 if (skyrendermasked)
10740                 {
10741                         R_SetupShader_DepthOrShadow(false, false, false);
10742                         // depth-only (masking)
10743                         GL_ColorMask(0,0,0,0);
10744                         // just to make sure that braindead drivers don't draw
10745                         // anything despite that colormask...
10746                         GL_BlendFunc(GL_ZERO, GL_ONE);
10747                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10748                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10749                 }
10750                 else
10751                 {
10752                         R_SetupShader_Generic_NoTexture(false, false);
10753                         // fog sky
10754                         GL_BlendFunc(GL_ONE, GL_ZERO);
10755                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10756                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10757                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10758                 }
10759                 RSurf_DrawBatch();
10760                 if (skyrendermasked)
10761                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10762         }
10763         R_Mesh_ResetTextureState();
10764         GL_Color(1, 1, 1, 1);
10765 }
10766
10767 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10768 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10769 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10770 {
10771         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10772                 return;
10773         if (prepass)
10774         {
10775                 // render screenspace normalmap to texture
10776                 GL_DepthMask(true);
10777                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10778                 RSurf_DrawBatch();
10779                 return;
10780         }
10781
10782         // bind lightmap texture
10783
10784         // water/refraction/reflection/camera surfaces have to be handled specially
10785         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10786         {
10787                 int start, end, startplaneindex;
10788                 for (start = 0;start < texturenumsurfaces;start = end)
10789                 {
10790                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10791                         if(startplaneindex < 0)
10792                         {
10793                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10794                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10795                                 end = start + 1;
10796                                 continue;
10797                         }
10798                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10799                                 ;
10800                         // now that we have a batch using the same planeindex, render it
10801                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10802                         {
10803                                 // render water or distortion background
10804                                 GL_DepthMask(true);
10805                                 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);
10806                                 RSurf_DrawBatch();
10807                                 // blend surface on top
10808                                 GL_DepthMask(false);
10809                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10810                                 RSurf_DrawBatch();
10811                         }
10812                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10813                         {
10814                                 // render surface with reflection texture as input
10815                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10816                                 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);
10817                                 RSurf_DrawBatch();
10818                         }
10819                 }
10820                 return;
10821         }
10822
10823         // render surface batch normally
10824         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10825         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);
10826         RSurf_DrawBatch();
10827 }
10828
10829 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10830 {
10831         // OpenGL 1.3 path - anything not completely ancient
10832         qboolean applycolor;
10833         qboolean applyfog;
10834         int layerindex;
10835         const texturelayer_t *layer;
10836         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);
10837         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10838
10839         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10840         {
10841                 vec4_t layercolor;
10842                 int layertexrgbscale;
10843                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10844                 {
10845                         if (layerindex == 0)
10846                                 GL_AlphaTest(true);
10847                         else
10848                         {
10849                                 GL_AlphaTest(false);
10850                                 GL_DepthFunc(GL_EQUAL);
10851                         }
10852                 }
10853                 GL_DepthMask(layer->depthmask && writedepth);
10854                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10855                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10856                 {
10857                         layertexrgbscale = 4;
10858                         VectorScale(layer->color, 0.25f, layercolor);
10859                 }
10860                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10861                 {
10862                         layertexrgbscale = 2;
10863                         VectorScale(layer->color, 0.5f, layercolor);
10864                 }
10865                 else
10866                 {
10867                         layertexrgbscale = 1;
10868                         VectorScale(layer->color, 1.0f, layercolor);
10869                 }
10870                 layercolor[3] = layer->color[3];
10871                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10872                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10873                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10874                 switch (layer->type)
10875                 {
10876                 case TEXTURELAYERTYPE_LITTEXTURE:
10877                         // single-pass lightmapped texture with 2x rgbscale
10878                         R_Mesh_TexBind(0, r_texture_white);
10879                         R_Mesh_TexMatrix(0, NULL);
10880                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10881                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10882                         R_Mesh_TexBind(1, layer->texture);
10883                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10884                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10885                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10886                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10887                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10888                         else if (FAKELIGHT_ENABLED)
10889                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10890                         else if (rsurface.uselightmaptexture)
10891                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10892                         else
10893                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10894                         break;
10895                 case TEXTURELAYERTYPE_TEXTURE:
10896                         // singletexture unlit texture with transparency support
10897                         R_Mesh_TexBind(0, layer->texture);
10898                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10899                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10900                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10901                         R_Mesh_TexBind(1, 0);
10902                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10903                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10904                         break;
10905                 case TEXTURELAYERTYPE_FOG:
10906                         // singletexture fogging
10907                         if (layer->texture)
10908                         {
10909                                 R_Mesh_TexBind(0, layer->texture);
10910                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10911                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10912                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10913                         }
10914                         else
10915                         {
10916                                 R_Mesh_TexBind(0, 0);
10917                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10918                         }
10919                         R_Mesh_TexBind(1, 0);
10920                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10921                         // generate a color array for the fog pass
10922                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10923                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10924                         RSurf_DrawBatch();
10925                         break;
10926                 default:
10927                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10928                 }
10929         }
10930         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10931         {
10932                 GL_DepthFunc(GL_LEQUAL);
10933                 GL_AlphaTest(false);
10934         }
10935 }
10936
10937 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10938 {
10939         // OpenGL 1.1 - crusty old voodoo path
10940         qboolean applyfog;
10941         int layerindex;
10942         const texturelayer_t *layer;
10943         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);
10944         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10945
10946         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10947         {
10948                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10949                 {
10950                         if (layerindex == 0)
10951                                 GL_AlphaTest(true);
10952                         else
10953                         {
10954                                 GL_AlphaTest(false);
10955                                 GL_DepthFunc(GL_EQUAL);
10956                         }
10957                 }
10958                 GL_DepthMask(layer->depthmask && writedepth);
10959                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10960                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10961                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10962                 switch (layer->type)
10963                 {
10964                 case TEXTURELAYERTYPE_LITTEXTURE:
10965                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10966                         {
10967                                 // two-pass lit texture with 2x rgbscale
10968                                 // first the lightmap pass
10969                                 R_Mesh_TexBind(0, r_texture_white);
10970                                 R_Mesh_TexMatrix(0, NULL);
10971                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10972                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10973                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10974                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10975                                 else if (FAKELIGHT_ENABLED)
10976                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10977                                 else if (rsurface.uselightmaptexture)
10978                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10979                                 else
10980                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10981                                 // then apply the texture to it
10982                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10983                                 R_Mesh_TexBind(0, layer->texture);
10984                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10985                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10986                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10987                                 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);
10988                         }
10989                         else
10990                         {
10991                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10992                                 R_Mesh_TexBind(0, layer->texture);
10993                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10994                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10995                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10996                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10997                                         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);
10998                                 else if (FAKELIGHT_ENABLED)
10999                                         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);
11000                                 else
11001                                         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);
11002                         }
11003                         break;
11004                 case TEXTURELAYERTYPE_TEXTURE:
11005                         // singletexture unlit texture with transparency support
11006                         R_Mesh_TexBind(0, layer->texture);
11007                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11008                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11009                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11010                         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);
11011                         break;
11012                 case TEXTURELAYERTYPE_FOG:
11013                         // singletexture fogging
11014                         if (layer->texture)
11015                         {
11016                                 R_Mesh_TexBind(0, layer->texture);
11017                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11018                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11019                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11020                         }
11021                         else
11022                         {
11023                                 R_Mesh_TexBind(0, 0);
11024                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11025                         }
11026                         // generate a color array for the fog pass
11027                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11028                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11029                         RSurf_DrawBatch();
11030                         break;
11031                 default:
11032                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11033                 }
11034         }
11035         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11036         {
11037                 GL_DepthFunc(GL_LEQUAL);
11038                 GL_AlphaTest(false);
11039         }
11040 }
11041
11042 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11043 {
11044         int vi;
11045         int j;
11046         r_vertexgeneric_t *batchvertex;
11047         float c[4];
11048
11049 //      R_Mesh_ResetTextureState();
11050         R_SetupShader_Generic_NoTexture(false, false);
11051
11052         if(rsurface.texture && rsurface.texture->currentskinframe)
11053         {
11054                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11055                 c[3] *= rsurface.texture->currentalpha;
11056         }
11057         else
11058         {
11059                 c[0] = 1;
11060                 c[1] = 0;
11061                 c[2] = 1;
11062                 c[3] = 1;
11063         }
11064
11065         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11066         {
11067                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11068                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11069                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11070         }
11071
11072         // brighten it up (as texture value 127 means "unlit")
11073         c[0] *= 2 * r_refdef.view.colorscale;
11074         c[1] *= 2 * r_refdef.view.colorscale;
11075         c[2] *= 2 * r_refdef.view.colorscale;
11076
11077         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11078                 c[3] *= r_wateralpha.value;
11079
11080         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11081         {
11082                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11083                 GL_DepthMask(false);
11084         }
11085         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11086         {
11087                 GL_BlendFunc(GL_ONE, GL_ONE);
11088                 GL_DepthMask(false);
11089         }
11090         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11091         {
11092                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11093                 GL_DepthMask(false);
11094         }
11095         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11096         {
11097                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11098                 GL_DepthMask(false);
11099         }
11100         else
11101         {
11102                 GL_BlendFunc(GL_ONE, GL_ZERO);
11103                 GL_DepthMask(writedepth);
11104         }
11105
11106         if (r_showsurfaces.integer == 3)
11107         {
11108                 rsurface.passcolor4f = NULL;
11109
11110                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11111                 {
11112                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11113
11114                         rsurface.passcolor4f = NULL;
11115                         rsurface.passcolor4f_vertexbuffer = 0;
11116                         rsurface.passcolor4f_bufferoffset = 0;
11117                 }
11118                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11119                 {
11120                         qboolean applycolor = true;
11121                         float one = 1.0;
11122
11123                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11124
11125                         r_refdef.lightmapintensity = 1;
11126                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11127                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11128                 }
11129                 else if (FAKELIGHT_ENABLED)
11130                 {
11131                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11132
11133                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11134                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11135                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11136                 }
11137                 else
11138                 {
11139                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11140
11141                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11142                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11143                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11144                 }
11145
11146                 if(!rsurface.passcolor4f)
11147                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11148
11149                 RSurf_DrawBatch_GL11_ApplyAmbient();
11150                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11151                 if(r_refdef.fogenabled)
11152                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11153                 RSurf_DrawBatch_GL11_ClampColor();
11154
11155                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11156                 R_SetupShader_Generic_NoTexture(false, false);
11157                 RSurf_DrawBatch();
11158         }
11159         else if (!r_refdef.view.showdebug)
11160         {
11161                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11162                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11163                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11164                 {
11165                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11166                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11167                 }
11168                 R_Mesh_PrepareVertices_Generic_Unlock();
11169                 RSurf_DrawBatch();
11170         }
11171         else if (r_showsurfaces.integer == 4)
11172         {
11173                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11174                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11175                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11176                 {
11177                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11178                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11179                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11180                 }
11181                 R_Mesh_PrepareVertices_Generic_Unlock();
11182                 RSurf_DrawBatch();
11183         }
11184         else if (r_showsurfaces.integer == 2)
11185         {
11186                 const int *e;
11187                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11188                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11189                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11190                 {
11191                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11192                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11193                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11194                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11195                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11196                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11197                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11198                 }
11199                 R_Mesh_PrepareVertices_Generic_Unlock();
11200                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11201         }
11202         else
11203         {
11204                 int texturesurfaceindex;
11205                 int k;
11206                 const msurface_t *surface;
11207                 float surfacecolor4f[4];
11208                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11209                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11210                 vi = 0;
11211                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11212                 {
11213                         surface = texturesurfacelist[texturesurfaceindex];
11214                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11215                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11216                         for (j = 0;j < surface->num_vertices;j++)
11217                         {
11218                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11219                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11220                                 vi++;
11221                         }
11222                 }
11223                 R_Mesh_PrepareVertices_Generic_Unlock();
11224                 RSurf_DrawBatch();
11225         }
11226 }
11227
11228 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11229 {
11230         CHECKGLERROR
11231         RSurf_SetupDepthAndCulling();
11232         if (r_showsurfaces.integer)
11233         {
11234                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11235                 return;
11236         }
11237         switch (vid.renderpath)
11238         {
11239         case RENDERPATH_GL20:
11240         case RENDERPATH_D3D9:
11241         case RENDERPATH_D3D10:
11242         case RENDERPATH_D3D11:
11243         case RENDERPATH_SOFT:
11244         case RENDERPATH_GLES2:
11245                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11246                 break;
11247         case RENDERPATH_GL13:
11248         case RENDERPATH_GLES1:
11249                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11250                 break;
11251         case RENDERPATH_GL11:
11252                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11253                 break;
11254         }
11255         CHECKGLERROR
11256 }
11257
11258 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11259 {
11260         CHECKGLERROR
11261         RSurf_SetupDepthAndCulling();
11262         if (r_showsurfaces.integer)
11263         {
11264                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11265                 return;
11266         }
11267         switch (vid.renderpath)
11268         {
11269         case RENDERPATH_GL20:
11270         case RENDERPATH_D3D9:
11271         case RENDERPATH_D3D10:
11272         case RENDERPATH_D3D11:
11273         case RENDERPATH_SOFT:
11274         case RENDERPATH_GLES2:
11275                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11276                 break;
11277         case RENDERPATH_GL13:
11278         case RENDERPATH_GLES1:
11279                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11280                 break;
11281         case RENDERPATH_GL11:
11282                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11283                 break;
11284         }
11285         CHECKGLERROR
11286 }
11287
11288 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11289 {
11290         int i, j;
11291         int texturenumsurfaces, endsurface;
11292         texture_t *texture;
11293         const msurface_t *surface;
11294         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11295
11296         // if the model is static it doesn't matter what value we give for
11297         // wantnormals and wanttangents, so this logic uses only rules applicable
11298         // to a model, knowing that they are meaningless otherwise
11299         if (ent == r_refdef.scene.worldentity)
11300                 RSurf_ActiveWorldEntity();
11301         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11302                 RSurf_ActiveModelEntity(ent, false, false, false);
11303         else
11304         {
11305                 switch (vid.renderpath)
11306                 {
11307                 case RENDERPATH_GL20:
11308                 case RENDERPATH_D3D9:
11309                 case RENDERPATH_D3D10:
11310                 case RENDERPATH_D3D11:
11311                 case RENDERPATH_SOFT:
11312                 case RENDERPATH_GLES2:
11313                         RSurf_ActiveModelEntity(ent, true, true, false);
11314                         break;
11315                 case RENDERPATH_GL11:
11316                 case RENDERPATH_GL13:
11317                 case RENDERPATH_GLES1:
11318                         RSurf_ActiveModelEntity(ent, true, false, false);
11319                         break;
11320                 }
11321         }
11322
11323         if (r_transparentdepthmasking.integer)
11324         {
11325                 qboolean setup = false;
11326                 for (i = 0;i < numsurfaces;i = j)
11327                 {
11328                         j = i + 1;
11329                         surface = rsurface.modelsurfaces + surfacelist[i];
11330                         texture = surface->texture;
11331                         rsurface.texture = R_GetCurrentTexture(texture);
11332                         rsurface.lightmaptexture = NULL;
11333                         rsurface.deluxemaptexture = NULL;
11334                         rsurface.uselightmaptexture = false;
11335                         // scan ahead until we find a different texture
11336                         endsurface = min(i + 1024, numsurfaces);
11337                         texturenumsurfaces = 0;
11338                         texturesurfacelist[texturenumsurfaces++] = surface;
11339                         for (;j < endsurface;j++)
11340                         {
11341                                 surface = rsurface.modelsurfaces + surfacelist[j];
11342                                 if (texture != surface->texture)
11343                                         break;
11344                                 texturesurfacelist[texturenumsurfaces++] = surface;
11345                         }
11346                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11347                                 continue;
11348                         // render the range of surfaces as depth
11349                         if (!setup)
11350                         {
11351                                 setup = true;
11352                                 GL_ColorMask(0,0,0,0);
11353                                 GL_Color(1,1,1,1);
11354                                 GL_DepthTest(true);
11355                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11356                                 GL_DepthMask(true);
11357 //                              R_Mesh_ResetTextureState();
11358                         }
11359                         RSurf_SetupDepthAndCulling();
11360                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11361                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11362                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11363                         RSurf_DrawBatch();
11364                 }
11365                 if (setup)
11366                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11367         }
11368
11369         for (i = 0;i < numsurfaces;i = j)
11370         {
11371                 j = i + 1;
11372                 surface = rsurface.modelsurfaces + surfacelist[i];
11373                 texture = surface->texture;
11374                 rsurface.texture = R_GetCurrentTexture(texture);
11375                 // scan ahead until we find a different texture
11376                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11377                 texturenumsurfaces = 0;
11378                 texturesurfacelist[texturenumsurfaces++] = surface;
11379                 if(FAKELIGHT_ENABLED)
11380                 {
11381                         rsurface.lightmaptexture = NULL;
11382                         rsurface.deluxemaptexture = NULL;
11383                         rsurface.uselightmaptexture = false;
11384                         for (;j < endsurface;j++)
11385                         {
11386                                 surface = rsurface.modelsurfaces + surfacelist[j];
11387                                 if (texture != surface->texture)
11388                                         break;
11389                                 texturesurfacelist[texturenumsurfaces++] = surface;
11390                         }
11391                 }
11392                 else
11393                 {
11394                         rsurface.lightmaptexture = surface->lightmaptexture;
11395                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11396                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11397                         for (;j < endsurface;j++)
11398                         {
11399                                 surface = rsurface.modelsurfaces + surfacelist[j];
11400                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11401                                         break;
11402                                 texturesurfacelist[texturenumsurfaces++] = surface;
11403                         }
11404                 }
11405                 // render the range of surfaces
11406                 if (ent == r_refdef.scene.worldentity)
11407                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11408                 else
11409                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11410         }
11411         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11412 }
11413
11414 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11415 {
11416         // transparent surfaces get pushed off into the transparent queue
11417         int surfacelistindex;
11418         const msurface_t *surface;
11419         vec3_t tempcenter, center;
11420         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11421         {
11422                 surface = texturesurfacelist[surfacelistindex];
11423                 if (r_transparent_sortsurfacesbynearest.integer)
11424                 {
11425                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11426                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11427                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11428                 }
11429                 else
11430                 {
11431                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11432                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11433                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11434                 }
11435                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11436                 if (rsurface.entity->transparent_offset) // transparent offset
11437                 {
11438                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11439                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11440                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11441                 }
11442                 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);
11443         }
11444 }
11445
11446 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11447 {
11448         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11449                 return;
11450         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11451                 return;
11452         RSurf_SetupDepthAndCulling();
11453         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11454         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11455         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11456         RSurf_DrawBatch();
11457 }
11458
11459 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11460 {
11461         CHECKGLERROR
11462         if (depthonly)
11463                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11464         else if (prepass)
11465         {
11466                 if (!rsurface.texture->currentnumlayers)
11467                         return;
11468                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11469                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11470                 else
11471                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11472         }
11473         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11474                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11475         else if (!rsurface.texture->currentnumlayers)
11476                 return;
11477         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11478         {
11479                 // in the deferred case, transparent surfaces were queued during prepass
11480                 if (!r_shadow_usingdeferredprepass)
11481                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11482         }
11483         else
11484         {
11485                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11486                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11487         }
11488         CHECKGLERROR
11489 }
11490
11491 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11492 {
11493         int i, j;
11494         texture_t *texture;
11495         R_FrameData_SetMark();
11496         // break the surface list down into batches by texture and use of lightmapping
11497         for (i = 0;i < numsurfaces;i = j)
11498         {
11499                 j = i + 1;
11500                 // texture is the base texture pointer, rsurface.texture is the
11501                 // current frame/skin the texture is directing us to use (for example
11502                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11503                 // use skin 1 instead)
11504                 texture = surfacelist[i]->texture;
11505                 rsurface.texture = R_GetCurrentTexture(texture);
11506                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11507                 {
11508                         // if this texture is not the kind we want, skip ahead to the next one
11509                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11510                                 ;
11511                         continue;
11512                 }
11513                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11514                 {
11515                         rsurface.lightmaptexture = NULL;
11516                         rsurface.deluxemaptexture = NULL;
11517                         rsurface.uselightmaptexture = false;
11518                         // simply scan ahead until we find a different texture or lightmap state
11519                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11520                                 ;
11521                 }
11522                 else
11523                 {
11524                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11525                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11526                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11527                         // simply scan ahead until we find a different texture or lightmap state
11528                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11529                                 ;
11530                 }
11531                 // render the range of surfaces
11532                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11533         }
11534         R_FrameData_ReturnToMark();
11535 }
11536
11537 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11538 {
11539         CHECKGLERROR
11540         if (depthonly)
11541                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11542         else if (prepass)
11543         {
11544                 if (!rsurface.texture->currentnumlayers)
11545                         return;
11546                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11547                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11548                 else
11549                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11550         }
11551         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11552                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11553         else if (!rsurface.texture->currentnumlayers)
11554                 return;
11555         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11556         {
11557                 // in the deferred case, transparent surfaces were queued during prepass
11558                 if (!r_shadow_usingdeferredprepass)
11559                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11560         }
11561         else
11562         {
11563                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11564                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11565         }
11566         CHECKGLERROR
11567 }
11568
11569 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11570 {
11571         int i, j;
11572         texture_t *texture;
11573         R_FrameData_SetMark();
11574         // break the surface list down into batches by texture and use of lightmapping
11575         for (i = 0;i < numsurfaces;i = j)
11576         {
11577                 j = i + 1;
11578                 // texture is the base texture pointer, rsurface.texture is the
11579                 // current frame/skin the texture is directing us to use (for example
11580                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11581                 // use skin 1 instead)
11582                 texture = surfacelist[i]->texture;
11583                 rsurface.texture = R_GetCurrentTexture(texture);
11584                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11585                 {
11586                         // if this texture is not the kind we want, skip ahead to the next one
11587                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11588                                 ;
11589                         continue;
11590                 }
11591                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11592                 {
11593                         rsurface.lightmaptexture = NULL;
11594                         rsurface.deluxemaptexture = NULL;
11595                         rsurface.uselightmaptexture = false;
11596                         // simply scan ahead until we find a different texture or lightmap state
11597                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11598                                 ;
11599                 }
11600                 else
11601                 {
11602                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11603                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11604                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11605                         // simply scan ahead until we find a different texture or lightmap state
11606                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11607                                 ;
11608                 }
11609                 // render the range of surfaces
11610                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11611         }
11612         R_FrameData_ReturnToMark();
11613 }
11614
11615 float locboxvertex3f[6*4*3] =
11616 {
11617         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11618         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11619         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11620         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11621         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11622         1,0,0, 0,0,0, 0,1,0, 1,1,0
11623 };
11624
11625 unsigned short locboxelements[6*2*3] =
11626 {
11627          0, 1, 2, 0, 2, 3,
11628          4, 5, 6, 4, 6, 7,
11629          8, 9,10, 8,10,11,
11630         12,13,14, 12,14,15,
11631         16,17,18, 16,18,19,
11632         20,21,22, 20,22,23
11633 };
11634
11635 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11636 {
11637         int i, j;
11638         cl_locnode_t *loc = (cl_locnode_t *)ent;
11639         vec3_t mins, size;
11640         float vertex3f[6*4*3];
11641         CHECKGLERROR
11642         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11643         GL_DepthMask(false);
11644         GL_DepthRange(0, 1);
11645         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11646         GL_DepthTest(true);
11647         GL_CullFace(GL_NONE);
11648         R_EntityMatrix(&identitymatrix);
11649
11650 //      R_Mesh_ResetTextureState();
11651
11652         i = surfacelist[0];
11653         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11654                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11655                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11656                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11657
11658         if (VectorCompare(loc->mins, loc->maxs))
11659         {
11660                 VectorSet(size, 2, 2, 2);
11661                 VectorMA(loc->mins, -0.5f, size, mins);
11662         }
11663         else
11664         {
11665                 VectorCopy(loc->mins, mins);
11666                 VectorSubtract(loc->maxs, loc->mins, size);
11667         }
11668
11669         for (i = 0;i < 6*4*3;)
11670                 for (j = 0;j < 3;j++, i++)
11671                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11672
11673         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11674         R_SetupShader_Generic_NoTexture(false, false);
11675         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11676 }
11677
11678 void R_DrawLocs(void)
11679 {
11680         int index;
11681         cl_locnode_t *loc, *nearestloc;
11682         vec3_t center;
11683         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11684         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11685         {
11686                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11687                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11688         }
11689 }
11690
11691 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11692 {
11693         if (decalsystem->decals)
11694                 Mem_Free(decalsystem->decals);
11695         memset(decalsystem, 0, sizeof(*decalsystem));
11696 }
11697
11698 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)
11699 {
11700         tridecal_t *decal;
11701         tridecal_t *decals;
11702         int i;
11703
11704         // expand or initialize the system
11705         if (decalsystem->maxdecals <= decalsystem->numdecals)
11706         {
11707                 decalsystem_t old = *decalsystem;
11708                 qboolean useshortelements;
11709                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11710                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11711                 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)));
11712                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11713                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11714                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11715                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11716                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11717                 if (decalsystem->numdecals)
11718                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11719                 if (old.decals)
11720                         Mem_Free(old.decals);
11721                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11722                         decalsystem->element3i[i] = i;
11723                 if (useshortelements)
11724                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11725                                 decalsystem->element3s[i] = i;
11726         }
11727
11728         // grab a decal and search for another free slot for the next one
11729         decals = decalsystem->decals;
11730         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11731         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11732                 ;
11733         decalsystem->freedecal = i;
11734         if (decalsystem->numdecals <= i)
11735                 decalsystem->numdecals = i + 1;
11736
11737         // initialize the decal
11738         decal->lived = 0;
11739         decal->triangleindex = triangleindex;
11740         decal->surfaceindex = surfaceindex;
11741         decal->decalsequence = decalsequence;
11742         decal->color4f[0][0] = c0[0];
11743         decal->color4f[0][1] = c0[1];
11744         decal->color4f[0][2] = c0[2];
11745         decal->color4f[0][3] = 1;
11746         decal->color4f[1][0] = c1[0];
11747         decal->color4f[1][1] = c1[1];
11748         decal->color4f[1][2] = c1[2];
11749         decal->color4f[1][3] = 1;
11750         decal->color4f[2][0] = c2[0];
11751         decal->color4f[2][1] = c2[1];
11752         decal->color4f[2][2] = c2[2];
11753         decal->color4f[2][3] = 1;
11754         decal->vertex3f[0][0] = v0[0];
11755         decal->vertex3f[0][1] = v0[1];
11756         decal->vertex3f[0][2] = v0[2];
11757         decal->vertex3f[1][0] = v1[0];
11758         decal->vertex3f[1][1] = v1[1];
11759         decal->vertex3f[1][2] = v1[2];
11760         decal->vertex3f[2][0] = v2[0];
11761         decal->vertex3f[2][1] = v2[1];
11762         decal->vertex3f[2][2] = v2[2];
11763         decal->texcoord2f[0][0] = t0[0];
11764         decal->texcoord2f[0][1] = t0[1];
11765         decal->texcoord2f[1][0] = t1[0];
11766         decal->texcoord2f[1][1] = t1[1];
11767         decal->texcoord2f[2][0] = t2[0];
11768         decal->texcoord2f[2][1] = t2[1];
11769         TriangleNormal(v0, v1, v2, decal->plane);
11770         VectorNormalize(decal->plane);
11771         decal->plane[3] = DotProduct(v0, decal->plane);
11772 }
11773
11774 extern cvar_t cl_decals_bias;
11775 extern cvar_t cl_decals_models;
11776 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11777 // baseparms, parms, temps
11778 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)
11779 {
11780         int cornerindex;
11781         int index;
11782         float v[9][3];
11783         const float *vertex3f;
11784         const float *normal3f;
11785         int numpoints;
11786         float points[2][9][3];
11787         float temp[3];
11788         float tc[9][2];
11789         float f;
11790         float c[9][4];
11791         const int *e;
11792
11793         e = rsurface.modelelement3i + 3*triangleindex;
11794
11795         vertex3f = rsurface.modelvertex3f;
11796         normal3f = rsurface.modelnormal3f;
11797
11798         if (normal3f)
11799         {
11800                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11801                 {
11802                         index = 3*e[cornerindex];
11803                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11804                 }
11805         }
11806         else
11807         {
11808                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11809                 {
11810                         index = 3*e[cornerindex];
11811                         VectorCopy(vertex3f + index, v[cornerindex]);
11812                 }
11813         }
11814
11815         // cull backfaces
11816         //TriangleNormal(v[0], v[1], v[2], normal);
11817         //if (DotProduct(normal, localnormal) < 0.0f)
11818         //      continue;
11819         // clip by each of the box planes formed from the projection matrix
11820         // if anything survives, we emit the decal
11821         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]);
11822         if (numpoints < 3)
11823                 return;
11824         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]);
11825         if (numpoints < 3)
11826                 return;
11827         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]);
11828         if (numpoints < 3)
11829                 return;
11830         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]);
11831         if (numpoints < 3)
11832                 return;
11833         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]);
11834         if (numpoints < 3)
11835                 return;
11836         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]);
11837         if (numpoints < 3)
11838                 return;
11839         // some part of the triangle survived, so we have to accept it...
11840         if (dynamic)
11841         {
11842                 // dynamic always uses the original triangle
11843                 numpoints = 3;
11844                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11845                 {
11846                         index = 3*e[cornerindex];
11847                         VectorCopy(vertex3f + index, v[cornerindex]);
11848                 }
11849         }
11850         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11851         {
11852                 // convert vertex positions to texcoords
11853                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11854                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11855                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11856                 // calculate distance fade from the projection origin
11857                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11858                 f = bound(0.0f, f, 1.0f);
11859                 c[cornerindex][0] = r * f;
11860                 c[cornerindex][1] = g * f;
11861                 c[cornerindex][2] = b * f;
11862                 c[cornerindex][3] = 1.0f;
11863                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11864         }
11865         if (dynamic)
11866                 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);
11867         else
11868                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11869                         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);
11870 }
11871 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)
11872 {
11873         matrix4x4_t projection;
11874         decalsystem_t *decalsystem;
11875         qboolean dynamic;
11876         dp_model_t *model;
11877         const msurface_t *surface;
11878         const msurface_t *surfaces;
11879         const int *surfacelist;
11880         const texture_t *texture;
11881         int numtriangles;
11882         int numsurfacelist;
11883         int surfacelistindex;
11884         int surfaceindex;
11885         int triangleindex;
11886         float localorigin[3];
11887         float localnormal[3];
11888         float localmins[3];
11889         float localmaxs[3];
11890         float localsize;
11891         //float normal[3];
11892         float planes[6][4];
11893         float angles[3];
11894         bih_t *bih;
11895         int bih_triangles_count;
11896         int bih_triangles[256];
11897         int bih_surfaces[256];
11898
11899         decalsystem = &ent->decalsystem;
11900         model = ent->model;
11901         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11902         {
11903                 R_DecalSystem_Reset(&ent->decalsystem);
11904                 return;
11905         }
11906
11907         if (!model->brush.data_leafs && !cl_decals_models.integer)
11908         {
11909                 if (decalsystem->model)
11910                         R_DecalSystem_Reset(decalsystem);
11911                 return;
11912         }
11913
11914         if (decalsystem->model != model)
11915                 R_DecalSystem_Reset(decalsystem);
11916         decalsystem->model = model;
11917
11918         RSurf_ActiveModelEntity(ent, true, false, false);
11919
11920         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11921         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11922         VectorNormalize(localnormal);
11923         localsize = worldsize*rsurface.inversematrixscale;
11924         localmins[0] = localorigin[0] - localsize;
11925         localmins[1] = localorigin[1] - localsize;
11926         localmins[2] = localorigin[2] - localsize;
11927         localmaxs[0] = localorigin[0] + localsize;
11928         localmaxs[1] = localorigin[1] + localsize;
11929         localmaxs[2] = localorigin[2] + localsize;
11930
11931         //VectorCopy(localnormal, planes[4]);
11932         //VectorVectors(planes[4], planes[2], planes[0]);
11933         AnglesFromVectors(angles, localnormal, NULL, false);
11934         AngleVectors(angles, planes[0], planes[2], planes[4]);
11935         VectorNegate(planes[0], planes[1]);
11936         VectorNegate(planes[2], planes[3]);
11937         VectorNegate(planes[4], planes[5]);
11938         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11939         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11940         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11941         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11942         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11943         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11944
11945 #if 1
11946 // works
11947 {
11948         matrix4x4_t forwardprojection;
11949         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11950         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11951 }
11952 #else
11953 // broken
11954 {
11955         float projectionvector[4][3];
11956         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11957         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11958         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11959         projectionvector[0][0] = planes[0][0] * ilocalsize;
11960         projectionvector[0][1] = planes[1][0] * ilocalsize;
11961         projectionvector[0][2] = planes[2][0] * ilocalsize;
11962         projectionvector[1][0] = planes[0][1] * ilocalsize;
11963         projectionvector[1][1] = planes[1][1] * ilocalsize;
11964         projectionvector[1][2] = planes[2][1] * ilocalsize;
11965         projectionvector[2][0] = planes[0][2] * ilocalsize;
11966         projectionvector[2][1] = planes[1][2] * ilocalsize;
11967         projectionvector[2][2] = planes[2][2] * ilocalsize;
11968         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11969         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11970         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11971         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11972 }
11973 #endif
11974
11975         dynamic = model->surfmesh.isanimated;
11976         numsurfacelist = model->nummodelsurfaces;
11977         surfacelist = model->sortedmodelsurfaces;
11978         surfaces = model->data_surfaces;
11979
11980         bih = NULL;
11981         bih_triangles_count = -1;
11982         if(!dynamic)
11983         {
11984                 if(model->render_bih.numleafs)
11985                         bih = &model->render_bih;
11986                 else if(model->collision_bih.numleafs)
11987                         bih = &model->collision_bih;
11988         }
11989         if(bih)
11990                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11991         if(bih_triangles_count == 0)
11992                 return;
11993         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11994                 return;
11995         if(bih_triangles_count > 0)
11996         {
11997                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11998                 {
11999                         surfaceindex = bih_surfaces[triangleindex];
12000                         surface = surfaces + surfaceindex;
12001                         texture = surface->texture;
12002                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12003                                 continue;
12004                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12005                                 continue;
12006                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12007                 }
12008         }
12009         else
12010         {
12011                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12012                 {
12013                         surfaceindex = surfacelist[surfacelistindex];
12014                         surface = surfaces + surfaceindex;
12015                         // check cull box first because it rejects more than any other check
12016                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12017                                 continue;
12018                         // skip transparent surfaces
12019                         texture = surface->texture;
12020                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12021                                 continue;
12022                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12023                                 continue;
12024                         numtriangles = surface->num_triangles;
12025                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12026                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12027                 }
12028         }
12029 }
12030
12031 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12032 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)
12033 {
12034         int renderentityindex;
12035         float worldmins[3];
12036         float worldmaxs[3];
12037         entity_render_t *ent;
12038
12039         if (!cl_decals_newsystem.integer)
12040                 return;
12041
12042         worldmins[0] = worldorigin[0] - worldsize;
12043         worldmins[1] = worldorigin[1] - worldsize;
12044         worldmins[2] = worldorigin[2] - worldsize;
12045         worldmaxs[0] = worldorigin[0] + worldsize;
12046         worldmaxs[1] = worldorigin[1] + worldsize;
12047         worldmaxs[2] = worldorigin[2] + worldsize;
12048
12049         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12050
12051         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12052         {
12053                 ent = r_refdef.scene.entities[renderentityindex];
12054                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12055                         continue;
12056
12057                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12058         }
12059 }
12060
12061 typedef struct r_decalsystem_splatqueue_s
12062 {
12063         vec3_t worldorigin;
12064         vec3_t worldnormal;
12065         float color[4];
12066         float tcrange[4];
12067         float worldsize;
12068         unsigned int decalsequence;
12069 }
12070 r_decalsystem_splatqueue_t;
12071
12072 int r_decalsystem_numqueued = 0;
12073 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12074
12075 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)
12076 {
12077         r_decalsystem_splatqueue_t *queue;
12078
12079         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12080                 return;
12081
12082         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12083         VectorCopy(worldorigin, queue->worldorigin);
12084         VectorCopy(worldnormal, queue->worldnormal);
12085         Vector4Set(queue->color, r, g, b, a);
12086         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12087         queue->worldsize = worldsize;
12088         queue->decalsequence = cl.decalsequence++;
12089 }
12090
12091 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12092 {
12093         int i;
12094         r_decalsystem_splatqueue_t *queue;
12095
12096         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12097                 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);
12098         r_decalsystem_numqueued = 0;
12099 }
12100
12101 extern cvar_t cl_decals_max;
12102 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12103 {
12104         int i;
12105         decalsystem_t *decalsystem = &ent->decalsystem;
12106         int numdecals;
12107         unsigned int killsequence;
12108         tridecal_t *decal;
12109         float frametime;
12110         float lifetime;
12111
12112         if (!decalsystem->numdecals)
12113                 return;
12114
12115         if (r_showsurfaces.integer)
12116                 return;
12117
12118         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12119         {
12120                 R_DecalSystem_Reset(decalsystem);
12121                 return;
12122         }
12123
12124         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12125         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12126
12127         if (decalsystem->lastupdatetime)
12128                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12129         else
12130                 frametime = 0;
12131         decalsystem->lastupdatetime = r_refdef.scene.time;
12132         numdecals = decalsystem->numdecals;
12133
12134         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12135         {
12136                 if (decal->color4f[0][3])
12137                 {
12138                         decal->lived += frametime;
12139                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12140                         {
12141                                 memset(decal, 0, sizeof(*decal));
12142                                 if (decalsystem->freedecal > i)
12143                                         decalsystem->freedecal = i;
12144                         }
12145                 }
12146         }
12147         decal = decalsystem->decals;
12148         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12149                 numdecals--;
12150
12151         // collapse the array by shuffling the tail decals into the gaps
12152         for (;;)
12153         {
12154                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12155                         decalsystem->freedecal++;
12156                 if (decalsystem->freedecal == numdecals)
12157                         break;
12158                 decal[decalsystem->freedecal] = decal[--numdecals];
12159         }
12160
12161         decalsystem->numdecals = numdecals;
12162
12163         if (numdecals <= 0)
12164         {
12165                 // if there are no decals left, reset decalsystem
12166                 R_DecalSystem_Reset(decalsystem);
12167         }
12168 }
12169
12170 extern skinframe_t *decalskinframe;
12171 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12172 {
12173         int i;
12174         decalsystem_t *decalsystem = &ent->decalsystem;
12175         int numdecals;
12176         tridecal_t *decal;
12177         float faderate;
12178         float alpha;
12179         float *v3f;
12180         float *c4f;
12181         float *t2f;
12182         const int *e;
12183         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12184         int numtris = 0;
12185
12186         numdecals = decalsystem->numdecals;
12187         if (!numdecals)
12188                 return;
12189
12190         if (r_showsurfaces.integer)
12191                 return;
12192
12193         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12194         {
12195                 R_DecalSystem_Reset(decalsystem);
12196                 return;
12197         }
12198
12199         // if the model is static it doesn't matter what value we give for
12200         // wantnormals and wanttangents, so this logic uses only rules applicable
12201         // to a model, knowing that they are meaningless otherwise
12202         if (ent == r_refdef.scene.worldentity)
12203                 RSurf_ActiveWorldEntity();
12204         else
12205                 RSurf_ActiveModelEntity(ent, false, false, false);
12206
12207         decalsystem->lastupdatetime = r_refdef.scene.time;
12208
12209         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12210
12211         // update vertex positions for animated models
12212         v3f = decalsystem->vertex3f;
12213         c4f = decalsystem->color4f;
12214         t2f = decalsystem->texcoord2f;
12215         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12216         {
12217                 if (!decal->color4f[0][3])
12218                         continue;
12219
12220                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12221                         continue;
12222
12223                 // skip backfaces
12224                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12225                         continue;
12226
12227                 // update color values for fading decals
12228                 if (decal->lived >= cl_decals_time.value)
12229                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12230                 else
12231                         alpha = 1.0f;
12232
12233                 c4f[ 0] = decal->color4f[0][0] * alpha;
12234                 c4f[ 1] = decal->color4f[0][1] * alpha;
12235                 c4f[ 2] = decal->color4f[0][2] * alpha;
12236                 c4f[ 3] = 1;
12237                 c4f[ 4] = decal->color4f[1][0] * alpha;
12238                 c4f[ 5] = decal->color4f[1][1] * alpha;
12239                 c4f[ 6] = decal->color4f[1][2] * alpha;
12240                 c4f[ 7] = 1;
12241                 c4f[ 8] = decal->color4f[2][0] * alpha;
12242                 c4f[ 9] = decal->color4f[2][1] * alpha;
12243                 c4f[10] = decal->color4f[2][2] * alpha;
12244                 c4f[11] = 1;
12245
12246                 t2f[0] = decal->texcoord2f[0][0];
12247                 t2f[1] = decal->texcoord2f[0][1];
12248                 t2f[2] = decal->texcoord2f[1][0];
12249                 t2f[3] = decal->texcoord2f[1][1];
12250                 t2f[4] = decal->texcoord2f[2][0];
12251                 t2f[5] = decal->texcoord2f[2][1];
12252
12253                 // update vertex positions for animated models
12254                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12255                 {
12256                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12257                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12258                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12259                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12260                 }
12261                 else
12262                 {
12263                         VectorCopy(decal->vertex3f[0], v3f);
12264                         VectorCopy(decal->vertex3f[1], v3f + 3);
12265                         VectorCopy(decal->vertex3f[2], v3f + 6);
12266                 }
12267
12268                 if (r_refdef.fogenabled)
12269                 {
12270                         alpha = RSurf_FogVertex(v3f);
12271                         VectorScale(c4f, alpha, c4f);
12272                         alpha = RSurf_FogVertex(v3f + 3);
12273                         VectorScale(c4f + 4, alpha, c4f + 4);
12274                         alpha = RSurf_FogVertex(v3f + 6);
12275                         VectorScale(c4f + 8, alpha, c4f + 8);
12276                 }
12277
12278                 v3f += 9;
12279                 c4f += 12;
12280                 t2f += 6;
12281                 numtris++;
12282         }
12283
12284         if (numtris > 0)
12285         {
12286                 r_refdef.stats[r_stat_drawndecals] += numtris;
12287
12288                 // now render the decals all at once
12289                 // (this assumes they all use one particle font texture!)
12290                 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);
12291 //              R_Mesh_ResetTextureState();
12292                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12293                 GL_DepthMask(false);
12294                 GL_DepthRange(0, 1);
12295                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12296                 GL_DepthTest(true);
12297                 GL_CullFace(GL_NONE);
12298                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12299                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12300                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12301         }
12302 }
12303
12304 static void R_DrawModelDecals(void)
12305 {
12306         int i, numdecals;
12307
12308         // fade faster when there are too many decals
12309         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12310         for (i = 0;i < r_refdef.scene.numentities;i++)
12311                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12312
12313         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12314         for (i = 0;i < r_refdef.scene.numentities;i++)
12315                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12316                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12317
12318         R_DecalSystem_ApplySplatEntitiesQueue();
12319
12320         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12321         for (i = 0;i < r_refdef.scene.numentities;i++)
12322                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12323
12324         r_refdef.stats[r_stat_totaldecals] += numdecals;
12325
12326         if (r_showsurfaces.integer)
12327                 return;
12328
12329         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12330
12331         for (i = 0;i < r_refdef.scene.numentities;i++)
12332         {
12333                 if (!r_refdef.viewcache.entityvisible[i])
12334                         continue;
12335                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12336                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12337         }
12338 }
12339
12340 extern cvar_t mod_collision_bih;
12341 static void R_DrawDebugModel(void)
12342 {
12343         entity_render_t *ent = rsurface.entity;
12344         int i, j, flagsmask;
12345         const msurface_t *surface;
12346         dp_model_t *model = ent->model;
12347
12348         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12349                 return;
12350
12351         if (r_showoverdraw.value > 0)
12352         {
12353                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12354                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12355                 R_SetupShader_Generic_NoTexture(false, false);
12356                 GL_DepthTest(false);
12357                 GL_DepthMask(false);
12358                 GL_DepthRange(0, 1);
12359                 GL_BlendFunc(GL_ONE, GL_ONE);
12360                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12361                 {
12362                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12363                                 continue;
12364                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12365                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12366                         {
12367                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12368                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12369                                 if (!rsurface.texture->currentlayers->depthmask)
12370                                         GL_Color(c, 0, 0, 1.0f);
12371                                 else if (ent == r_refdef.scene.worldentity)
12372                                         GL_Color(c, c, c, 1.0f);
12373                                 else
12374                                         GL_Color(0, c, 0, 1.0f);
12375                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12376                                 RSurf_DrawBatch();
12377                         }
12378                 }
12379                 rsurface.texture = NULL;
12380         }
12381
12382         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12383
12384 //      R_Mesh_ResetTextureState();
12385         R_SetupShader_Generic_NoTexture(false, false);
12386         GL_DepthRange(0, 1);
12387         GL_DepthTest(!r_showdisabledepthtest.integer);
12388         GL_DepthMask(false);
12389         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12390
12391         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12392         {
12393                 int triangleindex;
12394                 int bihleafindex;
12395                 qboolean cullbox = false;
12396                 const q3mbrush_t *brush;
12397                 const bih_t *bih = &model->collision_bih;
12398                 const bih_leaf_t *bihleaf;
12399                 float vertex3f[3][3];
12400                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12401                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12402                 {
12403                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12404                                 continue;
12405                         switch (bihleaf->type)
12406                         {
12407                         case BIH_BRUSH:
12408                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12409                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12410                                 {
12411                                         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);
12412                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12413                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12414                                 }
12415                                 break;
12416                         case BIH_COLLISIONTRIANGLE:
12417                                 triangleindex = bihleaf->itemindex;
12418                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12419                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12420                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12421                                 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);
12422                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12423                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12424                                 break;
12425                         case BIH_RENDERTRIANGLE:
12426                                 triangleindex = bihleaf->itemindex;
12427                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12428                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12429                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12430                                 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);
12431                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12432                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12433                                 break;
12434                         }
12435                 }
12436         }
12437
12438         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12439
12440 #ifndef USE_GLES2
12441         if (r_showtris.integer && qglPolygonMode)
12442         {
12443                 if (r_showdisabledepthtest.integer)
12444                 {
12445                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12446                         GL_DepthMask(false);
12447                 }
12448                 else
12449                 {
12450                         GL_BlendFunc(GL_ONE, GL_ZERO);
12451                         GL_DepthMask(true);
12452                 }
12453                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12454                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12455                 {
12456                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12457                                 continue;
12458                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12459                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12460                         {
12461                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12462                                 if (!rsurface.texture->currentlayers->depthmask)
12463                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12464                                 else if (ent == r_refdef.scene.worldentity)
12465                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12466                                 else
12467                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12468                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12469                                 RSurf_DrawBatch();
12470                         }
12471                 }
12472                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12473                 rsurface.texture = NULL;
12474         }
12475
12476         if (r_shownormals.value != 0 && qglBegin)
12477         {
12478                 int l, k;
12479                 vec3_t v;
12480                 if (r_showdisabledepthtest.integer)
12481                 {
12482                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12483                         GL_DepthMask(false);
12484                 }
12485                 else
12486                 {
12487                         GL_BlendFunc(GL_ONE, GL_ZERO);
12488                         GL_DepthMask(true);
12489                 }
12490                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12491                 {
12492                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12493                                 continue;
12494                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12495                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12496                         {
12497                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12498                                 qglBegin(GL_LINES);
12499                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12500                                 {
12501                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12502                                         {
12503                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12504                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12505                                                 qglVertex3f(v[0], v[1], v[2]);
12506                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12507                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12508                                                 qglVertex3f(v[0], v[1], v[2]);
12509                                         }
12510                                 }
12511                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12512                                 {
12513                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12514                                         {
12515                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12516                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12517                                                 qglVertex3f(v[0], v[1], v[2]);
12518                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12519                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12520                                                 qglVertex3f(v[0], v[1], v[2]);
12521                                         }
12522                                 }
12523                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12524                                 {
12525                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12526                                         {
12527                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12528                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12529                                                 qglVertex3f(v[0], v[1], v[2]);
12530                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12531                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12532                                                 qglVertex3f(v[0], v[1], v[2]);
12533                                         }
12534                                 }
12535                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12536                                 {
12537                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12538                                         {
12539                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12540                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12541                                                 qglVertex3f(v[0], v[1], v[2]);
12542                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12543                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12544                                                 qglVertex3f(v[0], v[1], v[2]);
12545                                         }
12546                                 }
12547                                 qglEnd();
12548                                 CHECKGLERROR
12549                         }
12550                 }
12551                 rsurface.texture = NULL;
12552         }
12553 #endif
12554 }
12555
12556 int r_maxsurfacelist = 0;
12557 const msurface_t **r_surfacelist = NULL;
12558 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12559 {
12560         int i, j, endj, flagsmask;
12561         dp_model_t *model = r_refdef.scene.worldmodel;
12562         msurface_t *surfaces;
12563         unsigned char *update;
12564         int numsurfacelist = 0;
12565         if (model == NULL)
12566                 return;
12567
12568         if (r_maxsurfacelist < model->num_surfaces)
12569         {
12570                 r_maxsurfacelist = model->num_surfaces;
12571                 if (r_surfacelist)
12572                         Mem_Free((msurface_t**)r_surfacelist);
12573                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12574         }
12575
12576         RSurf_ActiveWorldEntity();
12577
12578         surfaces = model->data_surfaces;
12579         update = model->brushq1.lightmapupdateflags;
12580
12581         // update light styles on this submodel
12582         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12583         {
12584                 model_brush_lightstyleinfo_t *style;
12585                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12586                 {
12587                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12588                         {
12589                                 int *list = style->surfacelist;
12590                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12591                                 for (j = 0;j < style->numsurfaces;j++)
12592                                         update[list[j]] = true;
12593                         }
12594                 }
12595         }
12596
12597         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12598
12599         if (debug)
12600         {
12601                 R_DrawDebugModel();
12602                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12603                 return;
12604         }
12605
12606         rsurface.lightmaptexture = NULL;
12607         rsurface.deluxemaptexture = NULL;
12608         rsurface.uselightmaptexture = false;
12609         rsurface.texture = NULL;
12610         rsurface.rtlight = NULL;
12611         numsurfacelist = 0;
12612         // add visible surfaces to draw list
12613         for (i = 0;i < model->nummodelsurfaces;i++)
12614         {
12615                 j = model->sortedmodelsurfaces[i];
12616                 if (r_refdef.viewcache.world_surfacevisible[j])
12617                         r_surfacelist[numsurfacelist++] = surfaces + j;
12618         }
12619         // update lightmaps if needed
12620         if (model->brushq1.firstrender)
12621         {
12622                 model->brushq1.firstrender = false;
12623                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12624                         if (update[j])
12625                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12626         }
12627         else if (update)
12628         {
12629                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12630                         if (r_refdef.viewcache.world_surfacevisible[j])
12631                                 if (update[j])
12632                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12633         }
12634         // don't do anything if there were no surfaces
12635         if (!numsurfacelist)
12636         {
12637                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12638                 return;
12639         }
12640         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12641
12642         // add to stats if desired
12643         if (r_speeds.integer && !skysurfaces && !depthonly)
12644         {
12645                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12646                 for (j = 0;j < numsurfacelist;j++)
12647                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12648         }
12649
12650         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12651 }
12652
12653 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12654 {
12655         int i, j, endj, flagsmask;
12656         dp_model_t *model = ent->model;
12657         msurface_t *surfaces;
12658         unsigned char *update;
12659         int numsurfacelist = 0;
12660         if (model == NULL)
12661                 return;
12662
12663         if (r_maxsurfacelist < model->num_surfaces)
12664         {
12665                 r_maxsurfacelist = model->num_surfaces;
12666                 if (r_surfacelist)
12667                         Mem_Free((msurface_t **)r_surfacelist);
12668                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12669         }
12670
12671         // if the model is static it doesn't matter what value we give for
12672         // wantnormals and wanttangents, so this logic uses only rules applicable
12673         // to a model, knowing that they are meaningless otherwise
12674         if (ent == r_refdef.scene.worldentity)
12675                 RSurf_ActiveWorldEntity();
12676         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12677                 RSurf_ActiveModelEntity(ent, false, false, false);
12678         else if (prepass)
12679                 RSurf_ActiveModelEntity(ent, true, true, true);
12680         else if (depthonly)
12681         {
12682                 switch (vid.renderpath)
12683                 {
12684                 case RENDERPATH_GL20:
12685                 case RENDERPATH_D3D9:
12686                 case RENDERPATH_D3D10:
12687                 case RENDERPATH_D3D11:
12688                 case RENDERPATH_SOFT:
12689                 case RENDERPATH_GLES2:
12690                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12691                         break;
12692                 case RENDERPATH_GL11:
12693                 case RENDERPATH_GL13:
12694                 case RENDERPATH_GLES1:
12695                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12696                         break;
12697                 }
12698         }
12699         else
12700         {
12701                 switch (vid.renderpath)
12702                 {
12703                 case RENDERPATH_GL20:
12704                 case RENDERPATH_D3D9:
12705                 case RENDERPATH_D3D10:
12706                 case RENDERPATH_D3D11:
12707                 case RENDERPATH_SOFT:
12708                 case RENDERPATH_GLES2:
12709                         RSurf_ActiveModelEntity(ent, true, true, false);
12710                         break;
12711                 case RENDERPATH_GL11:
12712                 case RENDERPATH_GL13:
12713                 case RENDERPATH_GLES1:
12714                         RSurf_ActiveModelEntity(ent, true, false, false);
12715                         break;
12716                 }
12717         }
12718
12719         surfaces = model->data_surfaces;
12720         update = model->brushq1.lightmapupdateflags;
12721
12722         // update light styles
12723         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12724         {
12725                 model_brush_lightstyleinfo_t *style;
12726                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12727                 {
12728                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12729                         {
12730                                 int *list = style->surfacelist;
12731                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12732                                 for (j = 0;j < style->numsurfaces;j++)
12733                                         update[list[j]] = true;
12734                         }
12735                 }
12736         }
12737
12738         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12739
12740         if (debug)
12741         {
12742                 R_DrawDebugModel();
12743                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12744                 return;
12745         }
12746
12747         rsurface.lightmaptexture = NULL;
12748         rsurface.deluxemaptexture = NULL;
12749         rsurface.uselightmaptexture = false;
12750         rsurface.texture = NULL;
12751         rsurface.rtlight = NULL;
12752         numsurfacelist = 0;
12753         // add visible surfaces to draw list
12754         for (i = 0;i < model->nummodelsurfaces;i++)
12755                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12756         // don't do anything if there were no surfaces
12757         if (!numsurfacelist)
12758         {
12759                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12760                 return;
12761         }
12762         // update lightmaps if needed
12763         if (update)
12764         {
12765                 int updated = 0;
12766                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12767                 {
12768                         if (update[j])
12769                         {
12770                                 updated++;
12771                                 R_BuildLightMap(ent, surfaces + j);
12772                         }
12773                 }
12774         }
12775
12776         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12777
12778         // add to stats if desired
12779         if (r_speeds.integer && !skysurfaces && !depthonly)
12780         {
12781                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12782                 for (j = 0;j < numsurfacelist;j++)
12783                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12784         }
12785
12786         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12787 }
12788
12789 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12790 {
12791         static texture_t texture;
12792         static msurface_t surface;
12793         const msurface_t *surfacelist = &surface;
12794
12795         // fake enough texture and surface state to render this geometry
12796
12797         texture.update_lastrenderframe = -1; // regenerate this texture
12798         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12799         texture.basealpha = 1.0f;
12800         texture.currentskinframe = skinframe;
12801         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12802         texture.offsetmapping = OFFSETMAPPING_OFF;
12803         texture.offsetscale = 1;
12804         texture.specularscalemod = 1;
12805         texture.specularpowermod = 1;
12806         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12807         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12808         // JUST GREP FOR "specularscalemod = 1".
12809
12810         surface.texture = &texture;
12811         surface.num_triangles = numtriangles;
12812         surface.num_firsttriangle = firsttriangle;
12813         surface.num_vertices = numvertices;
12814         surface.num_firstvertex = firstvertex;
12815
12816         // now render it
12817         rsurface.texture = R_GetCurrentTexture(surface.texture);
12818         rsurface.lightmaptexture = NULL;
12819         rsurface.deluxemaptexture = NULL;
12820         rsurface.uselightmaptexture = false;
12821         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12822 }
12823
12824 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)
12825 {
12826         static msurface_t surface;
12827         const msurface_t *surfacelist = &surface;
12828
12829         // fake enough texture and surface state to render this geometry
12830         surface.texture = texture;
12831         surface.num_triangles = numtriangles;
12832         surface.num_firsttriangle = firsttriangle;
12833         surface.num_vertices = numvertices;
12834         surface.num_firstvertex = firstvertex;
12835
12836         // now render it
12837         rsurface.texture = R_GetCurrentTexture(surface.texture);
12838         rsurface.lightmaptexture = NULL;
12839         rsurface.deluxemaptexture = NULL;
12840         rsurface.uselightmaptexture = false;
12841         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12842 }