]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
v_yshearing: Make view and input behave more like Duke Nukem 3D ;)
[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 char *glslshaderstring = NULL;
641 char *hlslshaderstring = NULL;
642
643 //=======================================================================================================================================================
644
645 typedef struct shaderpermutationinfo_s
646 {
647         const char *pretext;
648         const char *name;
649 }
650 shaderpermutationinfo_t;
651
652 typedef struct shadermodeinfo_s
653 {
654         const char *filename;
655         const char *pretext;
656         const char *name;
657 }
658 shadermodeinfo_t;
659
660 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
661 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
662 {
663         {"#define USEDIFFUSE\n", " diffuse"},
664         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
665         {"#define USEVIEWTINT\n", " viewtint"},
666         {"#define USECOLORMAPPING\n", " colormapping"},
667         {"#define USESATURATION\n", " saturation"},
668         {"#define USEFOGINSIDE\n", " foginside"},
669         {"#define USEFOGOUTSIDE\n", " fogoutside"},
670         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
671         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
672         {"#define USEGAMMARAMPS\n", " gammaramps"},
673         {"#define USECUBEFILTER\n", " cubefilter"},
674         {"#define USEGLOW\n", " glow"},
675         {"#define USEBLOOM\n", " bloom"},
676         {"#define USESPECULAR\n", " specular"},
677         {"#define USEPOSTPROCESSING\n", " postprocessing"},
678         {"#define USEREFLECTION\n", " reflection"},
679         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
680         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
681         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
682         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
683         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
684         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
685         {"#define USEALPHAKILL\n", " alphakill"},
686         {"#define USEREFLECTCUBE\n", " reflectcube"},
687         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
688         {"#define USEBOUNCEGRID\n", " bouncegrid"},
689         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
690         {"#define USETRIPPY\n", " trippy"},
691         {"#define USEDEPTHRGB\n", " depthrgb"},
692         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
693         {"#define USESKELETAL\n", " skeletal"},
694         {"#define USEOCCLUDE\n", " occlude"}
695 };
696
697 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
698 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
699 {
700         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
701         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
702         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
703         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
704         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
705         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
706         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
707         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
708         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
709         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
710         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
711         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
712         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
713         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
714         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
715         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
716         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
717 };
718
719 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
720 {
721         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
722         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
723         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
724         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
725         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
726         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
727         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
728         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
729         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
730         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
731         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
732         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
733         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
734         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
735         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
736         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
737         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
738 };
739
740 struct r_glsl_permutation_s;
741 typedef struct r_glsl_permutation_s
742 {
743         /// hash lookup data
744         struct r_glsl_permutation_s *hashnext;
745         unsigned int mode;
746         unsigned int permutation;
747
748         /// indicates if we have tried compiling this permutation already
749         qboolean compiled;
750         /// 0 if compilation failed
751         int program;
752         // texture units assigned to each detected uniform
753         int tex_Texture_First;
754         int tex_Texture_Second;
755         int tex_Texture_GammaRamps;
756         int tex_Texture_Normal;
757         int tex_Texture_Color;
758         int tex_Texture_Gloss;
759         int tex_Texture_Glow;
760         int tex_Texture_SecondaryNormal;
761         int tex_Texture_SecondaryColor;
762         int tex_Texture_SecondaryGloss;
763         int tex_Texture_SecondaryGlow;
764         int tex_Texture_Pants;
765         int tex_Texture_Shirt;
766         int tex_Texture_FogHeightTexture;
767         int tex_Texture_FogMask;
768         int tex_Texture_Lightmap;
769         int tex_Texture_Deluxemap;
770         int tex_Texture_Attenuation;
771         int tex_Texture_Cube;
772         int tex_Texture_Refraction;
773         int tex_Texture_Reflection;
774         int tex_Texture_ShadowMap2D;
775         int tex_Texture_CubeProjection;
776         int tex_Texture_ScreenNormalMap;
777         int tex_Texture_ScreenDiffuse;
778         int tex_Texture_ScreenSpecular;
779         int tex_Texture_ReflectMask;
780         int tex_Texture_ReflectCube;
781         int tex_Texture_BounceGrid;
782         /// locations of detected uniforms in program object, or -1 if not found
783         int loc_Texture_First;
784         int loc_Texture_Second;
785         int loc_Texture_GammaRamps;
786         int loc_Texture_Normal;
787         int loc_Texture_Color;
788         int loc_Texture_Gloss;
789         int loc_Texture_Glow;
790         int loc_Texture_SecondaryNormal;
791         int loc_Texture_SecondaryColor;
792         int loc_Texture_SecondaryGloss;
793         int loc_Texture_SecondaryGlow;
794         int loc_Texture_Pants;
795         int loc_Texture_Shirt;
796         int loc_Texture_FogHeightTexture;
797         int loc_Texture_FogMask;
798         int loc_Texture_Lightmap;
799         int loc_Texture_Deluxemap;
800         int loc_Texture_Attenuation;
801         int loc_Texture_Cube;
802         int loc_Texture_Refraction;
803         int loc_Texture_Reflection;
804         int loc_Texture_ShadowMap2D;
805         int loc_Texture_CubeProjection;
806         int loc_Texture_ScreenNormalMap;
807         int loc_Texture_ScreenDiffuse;
808         int loc_Texture_ScreenSpecular;
809         int loc_Texture_ReflectMask;
810         int loc_Texture_ReflectCube;
811         int loc_Texture_BounceGrid;
812         int loc_Alpha;
813         int loc_BloomBlur_Parameters;
814         int loc_ClientTime;
815         int loc_Color_Ambient;
816         int loc_Color_Diffuse;
817         int loc_Color_Specular;
818         int loc_Color_Glow;
819         int loc_Color_Pants;
820         int loc_Color_Shirt;
821         int loc_DeferredColor_Ambient;
822         int loc_DeferredColor_Diffuse;
823         int loc_DeferredColor_Specular;
824         int loc_DeferredMod_Diffuse;
825         int loc_DeferredMod_Specular;
826         int loc_DistortScaleRefractReflect;
827         int loc_EyePosition;
828         int loc_FogColor;
829         int loc_FogHeightFade;
830         int loc_FogPlane;
831         int loc_FogPlaneViewDist;
832         int loc_FogRangeRecip;
833         int loc_LightColor;
834         int loc_LightDir;
835         int loc_LightPosition;
836         int loc_OffsetMapping_ScaleSteps;
837         int loc_OffsetMapping_LodDistance;
838         int loc_OffsetMapping_Bias;
839         int loc_PixelSize;
840         int loc_ReflectColor;
841         int loc_ReflectFactor;
842         int loc_ReflectOffset;
843         int loc_RefractColor;
844         int loc_Saturation;
845         int loc_ScreenCenterRefractReflect;
846         int loc_ScreenScaleRefractReflect;
847         int loc_ScreenToDepth;
848         int loc_ShadowMap_Parameters;
849         int loc_ShadowMap_TextureScale;
850         int loc_SpecularPower;
851         int loc_Skeletal_Transform12;
852         int loc_UserVec1;
853         int loc_UserVec2;
854         int loc_UserVec3;
855         int loc_UserVec4;
856         int loc_ViewTintColor;
857         int loc_ViewToLight;
858         int loc_ModelToLight;
859         int loc_TexMatrix;
860         int loc_BackgroundTexMatrix;
861         int loc_ModelViewProjectionMatrix;
862         int loc_ModelViewMatrix;
863         int loc_PixelToScreenTexCoord;
864         int loc_ModelToReflectCube;
865         int loc_ShadowMapMatrix;
866         int loc_BloomColorSubtract;
867         int loc_NormalmapScrollBlend;
868         int loc_BounceGridMatrix;
869         int loc_BounceGridIntensity;
870         /// uniform block bindings
871         int ubibind_Skeletal_Transform12_UniformBlock;
872         /// uniform block indices
873         int ubiloc_Skeletal_Transform12_UniformBlock;
874 }
875 r_glsl_permutation_t;
876
877 #define SHADERPERMUTATION_HASHSIZE 256
878
879
880 // non-degradable "lightweight" shader parameters to keep the permutations simpler
881 // these can NOT degrade! only use for simple stuff
882 enum
883 {
884         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
885         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
886         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
887         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
888         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
889         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
890         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
891         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
892         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
893         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
894         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
895         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
896         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
897         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
898 };
899 #define SHADERSTATICPARMS_COUNT 14
900
901 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
902 static int shaderstaticparms_count = 0;
903
904 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
905 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
906
907 extern qboolean r_shadow_shadowmapsampler;
908 extern int r_shadow_shadowmappcf;
909 qboolean R_CompileShader_CheckStaticParms(void)
910 {
911         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
912         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
913         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
914
915         // detect all
916         if (r_glsl_saturation_redcompensate.integer)
917                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
918         if (r_glsl_vertextextureblend_usebothalphas.integer)
919                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
920         if (r_shadow_glossexact.integer)
921                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
922         if (r_glsl_postprocess.integer)
923         {
924                 if (r_glsl_postprocess_uservec1_enable.integer)
925                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
926                 if (r_glsl_postprocess_uservec2_enable.integer)
927                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
928                 if (r_glsl_postprocess_uservec3_enable.integer)
929                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
930                 if (r_glsl_postprocess_uservec4_enable.integer)
931                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
932         }
933         if (r_fxaa.integer)
934                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
935         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
936                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
937
938         if (r_shadow_shadowmapsampler)
939                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
940         if (r_shadow_shadowmappcf > 1)
941                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
942         else if (r_shadow_shadowmappcf)
943                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
944         if (r_celshading.integer)
945                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
946         if (r_celoutlines.integer)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
948
949         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
950 }
951
952 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
953         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
954                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
955         else \
956                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
957 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
958 {
959         shaderstaticparms_count = 0;
960
961         // emit all
962         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
963         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
964         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
965         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
966         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
967         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
968         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
969         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
972         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
973         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
976 }
977
978 /// information about each possible shader permutation
979 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
980 /// currently selected permutation
981 r_glsl_permutation_t *r_glsl_permutation;
982 /// storage for permutations linked in the hash table
983 memexpandablearray_t r_glsl_permutationarray;
984
985 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
986 {
987         //unsigned int hashdepth = 0;
988         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
989         r_glsl_permutation_t *p;
990         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
991         {
992                 if (p->mode == mode && p->permutation == permutation)
993                 {
994                         //if (hashdepth > 10)
995                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
996                         return p;
997                 }
998                 //hashdepth++;
999         }
1000         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1001         p->mode = mode;
1002         p->permutation = permutation;
1003         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1004         r_glsl_permutationhash[mode][hashindex] = p;
1005         //if (hashdepth > 10)
1006         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1007         return p;
1008 }
1009
1010 static char *R_ShaderStrCat(const char **strings)
1011 {
1012         char *string, *s;
1013         const char **p = strings;
1014         const char *t;
1015         size_t len = 0;
1016         for (p = strings;(t = *p);p++)
1017                 len += strlen(t);
1018         len++;
1019         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1020         len = 0;
1021         for (p = strings;(t = *p);p++)
1022         {
1023                 len = strlen(t);
1024                 memcpy(s, t, len);
1025                 s += len;
1026         }
1027         *s = 0;
1028         return string;
1029 }
1030
1031 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1032 {
1033         char *shaderstring;
1034         if (!filename || !filename[0])
1035                 return NULL;
1036         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1037         if (!strcmp(filename, "glsl/default.glsl"))
1038         {
1039                 if (builtinonly)
1040                         return R_ShaderStrCat(builtinshaderstrings);
1041                 if (!glslshaderstring)
1042                 {
1043                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1044                         if (glslshaderstring)
1045                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1046                         else
1047                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1048                 }
1049                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1050                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1051                 return shaderstring;
1052         }
1053         if (!strcmp(filename, "hlsl/default.hlsl"))
1054         {
1055                 if (builtinonly)
1056                         return R_ShaderStrCat(builtinhlslshaderstrings);
1057                 if (!hlslshaderstring)
1058                 {
1059                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1060                         if (hlslshaderstring)
1061                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1062                         else
1063                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1064                 }
1065                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1066                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1067                 return shaderstring;
1068         }
1069         // we don't have builtin strings for any other files
1070         if (builtinonly)
1071                 return NULL;
1072         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1073         if (shaderstring)
1074         {
1075                 if (printfromdisknotice)
1076                         Con_DPrintf("from disk %s... ", filename);
1077                 return shaderstring;
1078         }
1079         return shaderstring;
1080 }
1081
1082 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1083 {
1084         int i;
1085         int ubibind;
1086         int sampler;
1087         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1088         char *sourcestring;
1089         char permutationname[256];
1090         int vertstrings_count = 0;
1091         int geomstrings_count = 0;
1092         int fragstrings_count = 0;
1093         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1096
1097         if (p->compiled)
1098                 return;
1099         p->compiled = true;
1100         p->program = 0;
1101
1102         permutationname[0] = 0;
1103         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1104
1105         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1106
1107         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1108         if(vid.support.glshaderversion >= 140)
1109         {
1110                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1111                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1112                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1113                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1114                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1115                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1116         }
1117         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1118         else if(vid.support.glshaderversion >= 130)
1119         {
1120                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1121                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1122                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1123                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1124                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1125                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1126         }
1127
1128         // the first pretext is which type of shader to compile as
1129         // (later these will all be bound together as a program object)
1130         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1131         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1132         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1133
1134         // the second pretext is the mode (for example a light source)
1135         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1136         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1137         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1138         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1139
1140         // now add all the permutation pretexts
1141         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1142         {
1143                 if (permutation & (1<<i))
1144                 {
1145                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1146                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1147                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1148                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1149                 }
1150                 else
1151                 {
1152                         // keep line numbers correct
1153                         vertstrings_list[vertstrings_count++] = "\n";
1154                         geomstrings_list[geomstrings_count++] = "\n";
1155                         fragstrings_list[fragstrings_count++] = "\n";
1156                 }
1157         }
1158
1159         // add static parms
1160         R_CompileShader_AddStaticParms(mode, permutation);
1161         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1162         vertstrings_count += shaderstaticparms_count;
1163         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1164         geomstrings_count += shaderstaticparms_count;
1165         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1166         fragstrings_count += shaderstaticparms_count;
1167
1168         // now append the shader text itself
1169         vertstrings_list[vertstrings_count++] = sourcestring;
1170         geomstrings_list[geomstrings_count++] = sourcestring;
1171         fragstrings_list[fragstrings_count++] = sourcestring;
1172
1173         // compile the shader program
1174         if (vertstrings_count + geomstrings_count + fragstrings_count)
1175                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1176         if (p->program)
1177         {
1178                 CHECKGLERROR
1179                 qglUseProgram(p->program);CHECKGLERROR
1180                 // look up all the uniform variable names we care about, so we don't
1181                 // have to look them up every time we set them
1182
1183 #if 0
1184                 // debugging aid
1185                 {
1186                         GLint activeuniformindex = 0;
1187                         GLint numactiveuniforms = 0;
1188                         char uniformname[128];
1189                         GLsizei uniformnamelength = 0;
1190                         GLint uniformsize = 0;
1191                         GLenum uniformtype = 0;
1192                         memset(uniformname, 0, sizeof(uniformname));
1193                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1194                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1195                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1196                         {
1197                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1198                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1199                         }
1200                 }
1201 #endif
1202
1203                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1204                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1205                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1206                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1207                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1208                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1209                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1210                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1211                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1212                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1213                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1214                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1215                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1216                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1217                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1218                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1219                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1220                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1221                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1222                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1223                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1224                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1225                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1226                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1227                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1228                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1229                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1230                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1231                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1232                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1233                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1234                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1235                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1236                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1237                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1238                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1239                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1240                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1241                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1242                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1243                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1244                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1245                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1246                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1247                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1248                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1249                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1250                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1251                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1252                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1253                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1254                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1255                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1256                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1257                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1258                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1259                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1260                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1261                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1262                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1263                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1264                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1265                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1266                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1267                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1268                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1269                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1270                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1271                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1272                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1273                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1274                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1275                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1276                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1277                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1278                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1279                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1280                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1281                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1282                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1283                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1284                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1285                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1286                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1287                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1288                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1289                 // initialize the samplers to refer to the texture units we use
1290                 p->tex_Texture_First = -1;
1291                 p->tex_Texture_Second = -1;
1292                 p->tex_Texture_GammaRamps = -1;
1293                 p->tex_Texture_Normal = -1;
1294                 p->tex_Texture_Color = -1;
1295                 p->tex_Texture_Gloss = -1;
1296                 p->tex_Texture_Glow = -1;
1297                 p->tex_Texture_SecondaryNormal = -1;
1298                 p->tex_Texture_SecondaryColor = -1;
1299                 p->tex_Texture_SecondaryGloss = -1;
1300                 p->tex_Texture_SecondaryGlow = -1;
1301                 p->tex_Texture_Pants = -1;
1302                 p->tex_Texture_Shirt = -1;
1303                 p->tex_Texture_FogHeightTexture = -1;
1304                 p->tex_Texture_FogMask = -1;
1305                 p->tex_Texture_Lightmap = -1;
1306                 p->tex_Texture_Deluxemap = -1;
1307                 p->tex_Texture_Attenuation = -1;
1308                 p->tex_Texture_Cube = -1;
1309                 p->tex_Texture_Refraction = -1;
1310                 p->tex_Texture_Reflection = -1;
1311                 p->tex_Texture_ShadowMap2D = -1;
1312                 p->tex_Texture_CubeProjection = -1;
1313                 p->tex_Texture_ScreenNormalMap = -1;
1314                 p->tex_Texture_ScreenDiffuse = -1;
1315                 p->tex_Texture_ScreenSpecular = -1;
1316                 p->tex_Texture_ReflectMask = -1;
1317                 p->tex_Texture_ReflectCube = -1;
1318                 p->tex_Texture_BounceGrid = -1;
1319                 // bind the texture samplers in use
1320                 sampler = 0;
1321                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1322                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1323                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1324                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1325                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1326                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1327                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1328                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1329                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1330                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1331                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1332                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1333                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1334                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1335                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1336                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1337                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1338                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1339                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1340                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1341                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1342                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1343                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1344                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1345                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1346                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1347                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1348                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1349                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1350                 // get the uniform block indices so we can bind them
1351 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1352                 if (vid.support.arb_uniform_buffer_object)
1353                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1354                 else
1355 #endif
1356                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1357                 // clear the uniform block bindings
1358                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1359                 // bind the uniform blocks in use
1360                 ubibind = 0;
1361 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1362                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1363 #endif
1364                 // we're done compiling and setting up the shader, at least until it is used
1365                 CHECKGLERROR
1366                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1367         }
1368         else
1369                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1370
1371         // free the strings
1372         if (sourcestring)
1373                 Mem_Free(sourcestring);
1374 }
1375
1376 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1377 {
1378         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1379         if (r_glsl_permutation != perm)
1380         {
1381                 r_glsl_permutation = perm;
1382                 if (!r_glsl_permutation->program)
1383                 {
1384                         if (!r_glsl_permutation->compiled)
1385                         {
1386                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1387                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1388                         }
1389                         if (!r_glsl_permutation->program)
1390                         {
1391                                 // remove features until we find a valid permutation
1392                                 int i;
1393                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1394                                 {
1395                                         // reduce i more quickly whenever it would not remove any bits
1396                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1397                                         if (!(permutation & j))
1398                                                 continue;
1399                                         permutation -= j;
1400                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1401                                         if (!r_glsl_permutation->compiled)
1402                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1403                                         if (r_glsl_permutation->program)
1404                                                 break;
1405                                 }
1406                                 if (i >= SHADERPERMUTATION_COUNT)
1407                                 {
1408                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1409                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1410                                         qglUseProgram(0);CHECKGLERROR
1411                                         return; // no bit left to clear, entire mode is broken
1412                                 }
1413                         }
1414                 }
1415                 CHECKGLERROR
1416                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1417         }
1418         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1419         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1420         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1421         CHECKGLERROR
1422 }
1423
1424 #ifdef SUPPORTD3D
1425
1426 #ifdef SUPPORTD3D
1427 #include <d3d9.h>
1428 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1429 extern D3DCAPS9 vid_d3d9caps;
1430 #endif
1431
1432 struct r_hlsl_permutation_s;
1433 typedef struct r_hlsl_permutation_s
1434 {
1435         /// hash lookup data
1436         struct r_hlsl_permutation_s *hashnext;
1437         unsigned int mode;
1438         unsigned int permutation;
1439
1440         /// indicates if we have tried compiling this permutation already
1441         qboolean compiled;
1442         /// NULL if compilation failed
1443         IDirect3DVertexShader9 *vertexshader;
1444         IDirect3DPixelShader9 *pixelshader;
1445 }
1446 r_hlsl_permutation_t;
1447
1448 typedef enum D3DVSREGISTER_e
1449 {
1450         D3DVSREGISTER_TexMatrix = 0, // float4x4
1451         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1452         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1453         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1454         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1455         D3DVSREGISTER_ModelToLight = 20, // float4x4
1456         D3DVSREGISTER_EyePosition = 24,
1457         D3DVSREGISTER_FogPlane = 25,
1458         D3DVSREGISTER_LightDir = 26,
1459         D3DVSREGISTER_LightPosition = 27,
1460 }
1461 D3DVSREGISTER_t;
1462
1463 typedef enum D3DPSREGISTER_e
1464 {
1465         D3DPSREGISTER_Alpha = 0,
1466         D3DPSREGISTER_BloomBlur_Parameters = 1,
1467         D3DPSREGISTER_ClientTime = 2,
1468         D3DPSREGISTER_Color_Ambient = 3,
1469         D3DPSREGISTER_Color_Diffuse = 4,
1470         D3DPSREGISTER_Color_Specular = 5,
1471         D3DPSREGISTER_Color_Glow = 6,
1472         D3DPSREGISTER_Color_Pants = 7,
1473         D3DPSREGISTER_Color_Shirt = 8,
1474         D3DPSREGISTER_DeferredColor_Ambient = 9,
1475         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1476         D3DPSREGISTER_DeferredColor_Specular = 11,
1477         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1478         D3DPSREGISTER_DeferredMod_Specular = 13,
1479         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1480         D3DPSREGISTER_EyePosition = 15, // unused
1481         D3DPSREGISTER_FogColor = 16,
1482         D3DPSREGISTER_FogHeightFade = 17,
1483         D3DPSREGISTER_FogPlane = 18,
1484         D3DPSREGISTER_FogPlaneViewDist = 19,
1485         D3DPSREGISTER_FogRangeRecip = 20,
1486         D3DPSREGISTER_LightColor = 21,
1487         D3DPSREGISTER_LightDir = 22, // unused
1488         D3DPSREGISTER_LightPosition = 23,
1489         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1490         D3DPSREGISTER_PixelSize = 25,
1491         D3DPSREGISTER_ReflectColor = 26,
1492         D3DPSREGISTER_ReflectFactor = 27,
1493         D3DPSREGISTER_ReflectOffset = 28,
1494         D3DPSREGISTER_RefractColor = 29,
1495         D3DPSREGISTER_Saturation = 30,
1496         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1497         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1498         D3DPSREGISTER_ScreenToDepth = 33,
1499         D3DPSREGISTER_ShadowMap_Parameters = 34,
1500         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1501         D3DPSREGISTER_SpecularPower = 36,
1502         D3DPSREGISTER_UserVec1 = 37,
1503         D3DPSREGISTER_UserVec2 = 38,
1504         D3DPSREGISTER_UserVec3 = 39,
1505         D3DPSREGISTER_UserVec4 = 40,
1506         D3DPSREGISTER_ViewTintColor = 41,
1507         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1508         D3DPSREGISTER_BloomColorSubtract = 43,
1509         D3DPSREGISTER_ViewToLight = 44, // float4x4
1510         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1511         D3DPSREGISTER_NormalmapScrollBlend = 52,
1512         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1513         D3DPSREGISTER_OffsetMapping_Bias = 54,
1514         // next at 54
1515 }
1516 D3DPSREGISTER_t;
1517
1518 /// information about each possible shader permutation
1519 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1520 /// currently selected permutation
1521 r_hlsl_permutation_t *r_hlsl_permutation;
1522 /// storage for permutations linked in the hash table
1523 memexpandablearray_t r_hlsl_permutationarray;
1524
1525 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1526 {
1527         //unsigned int hashdepth = 0;
1528         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1529         r_hlsl_permutation_t *p;
1530         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1531         {
1532                 if (p->mode == mode && p->permutation == permutation)
1533                 {
1534                         //if (hashdepth > 10)
1535                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1536                         return p;
1537                 }
1538                 //hashdepth++;
1539         }
1540         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1541         p->mode = mode;
1542         p->permutation = permutation;
1543         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1544         r_hlsl_permutationhash[mode][hashindex] = p;
1545         //if (hashdepth > 10)
1546         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1547         return p;
1548 }
1549
1550 #include <d3dx9.h>
1551 //#include <d3dx9shader.h>
1552 //#include <d3dx9mesh.h>
1553
1554 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1555 {
1556         DWORD *vsbin = NULL;
1557         DWORD *psbin = NULL;
1558         fs_offset_t vsbinsize;
1559         fs_offset_t psbinsize;
1560 //      IDirect3DVertexShader9 *vs = NULL;
1561 //      IDirect3DPixelShader9 *ps = NULL;
1562         ID3DXBuffer *vslog = NULL;
1563         ID3DXBuffer *vsbuffer = NULL;
1564         ID3DXConstantTable *vsconstanttable = NULL;
1565         ID3DXBuffer *pslog = NULL;
1566         ID3DXBuffer *psbuffer = NULL;
1567         ID3DXConstantTable *psconstanttable = NULL;
1568         int vsresult = 0;
1569         int psresult = 0;
1570         char temp[MAX_INPUTLINE];
1571         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1572         char vabuf[1024];
1573         qboolean debugshader = gl_paranoid.integer != 0;
1574         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1575         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1576         if (!debugshader)
1577         {
1578                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1579                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1580         }
1581         if ((!vsbin && vertstring) || (!psbin && fragstring))
1582         {
1583                 const char* dllnames_d3dx9 [] =
1584                 {
1585                         "d3dx9_43.dll",
1586                         "d3dx9_42.dll",
1587                         "d3dx9_41.dll",
1588                         "d3dx9_40.dll",
1589                         "d3dx9_39.dll",
1590                         "d3dx9_38.dll",
1591                         "d3dx9_37.dll",
1592                         "d3dx9_36.dll",
1593                         "d3dx9_35.dll",
1594                         "d3dx9_34.dll",
1595                         "d3dx9_33.dll",
1596                         "d3dx9_32.dll",
1597                         "d3dx9_31.dll",
1598                         "d3dx9_30.dll",
1599                         "d3dx9_29.dll",
1600                         "d3dx9_28.dll",
1601                         "d3dx9_27.dll",
1602                         "d3dx9_26.dll",
1603                         "d3dx9_25.dll",
1604                         "d3dx9_24.dll",
1605                         NULL
1606                 };
1607                 dllhandle_t d3dx9_dll = NULL;
1608                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1609                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1610                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1611                 dllfunction_t d3dx9_dllfuncs[] =
1612                 {
1613                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1614                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1615                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1616                         {NULL, NULL}
1617                 };
1618                 // 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...
1619 #ifndef ID3DXBuffer_GetBufferPointer
1620 #if !defined(__cplusplus) || defined(CINTERFACE)
1621 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1622 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1623 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1624 #else
1625 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1626 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1627 #define ID3DXBuffer_Release(p)            (p)->Release()
1628 #endif
1629 #endif
1630                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1631                 {
1632                         DWORD shaderflags = 0;
1633                         if (debugshader)
1634                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1635                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1636                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1637                         if (vertstring && vertstring[0])
1638                         {
1639                                 if (debugshader)
1640                                 {
1641                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1642                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1643                                 }
1644                                 else
1645                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1646                                 if (vsbuffer)
1647                                 {
1648                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1649                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1650                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1651                                         ID3DXBuffer_Release(vsbuffer);
1652                                 }
1653                                 if (vslog)
1654                                 {
1655                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1656                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1657                                         ID3DXBuffer_Release(vslog);
1658                                 }
1659                         }
1660                         if (fragstring && fragstring[0])
1661                         {
1662                                 if (debugshader)
1663                                 {
1664                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1665                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1666                                 }
1667                                 else
1668                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1669                                 if (psbuffer)
1670                                 {
1671                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1672                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1673                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1674                                         ID3DXBuffer_Release(psbuffer);
1675                                 }
1676                                 if (pslog)
1677                                 {
1678                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1679                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1680                                         ID3DXBuffer_Release(pslog);
1681                                 }
1682                         }
1683                         Sys_UnloadLibrary(&d3dx9_dll);
1684                 }
1685                 else
1686                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1687         }
1688         if (vsbin && psbin)
1689         {
1690                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1691                 if (FAILED(vsresult))
1692                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1693                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1694                 if (FAILED(psresult))
1695                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1696         }
1697         // free the shader data
1698         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1699         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1700 }
1701
1702 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1703 {
1704         int i;
1705         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1706         int vertstring_length = 0;
1707         int geomstring_length = 0;
1708         int fragstring_length = 0;
1709         char *t;
1710         char *sourcestring;
1711         char *vertstring, *geomstring, *fragstring;
1712         char permutationname[256];
1713         char cachename[256];
1714         int vertstrings_count = 0;
1715         int geomstrings_count = 0;
1716         int fragstrings_count = 0;
1717         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1718         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1719         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1720
1721         if (p->compiled)
1722                 return;
1723         p->compiled = true;
1724         p->vertexshader = NULL;
1725         p->pixelshader = NULL;
1726
1727         permutationname[0] = 0;
1728         cachename[0] = 0;
1729         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1730
1731         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1732         strlcat(cachename, "hlsl/", sizeof(cachename));
1733
1734         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1735         vertstrings_count = 0;
1736         geomstrings_count = 0;
1737         fragstrings_count = 0;
1738         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1739         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1740         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1741
1742         // the first pretext is which type of shader to compile as
1743         // (later these will all be bound together as a program object)
1744         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1745         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1746         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1747
1748         // the second pretext is the mode (for example a light source)
1749         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1750         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1751         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1752         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1753         strlcat(cachename, modeinfo->name, sizeof(cachename));
1754
1755         // now add all the permutation pretexts
1756         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1757         {
1758                 if (permutation & (1<<i))
1759                 {
1760                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1761                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1762                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1763                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1764                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1765                 }
1766                 else
1767                 {
1768                         // keep line numbers correct
1769                         vertstrings_list[vertstrings_count++] = "\n";
1770                         geomstrings_list[geomstrings_count++] = "\n";
1771                         fragstrings_list[fragstrings_count++] = "\n";
1772                 }
1773         }
1774
1775         // add static parms
1776         R_CompileShader_AddStaticParms(mode, permutation);
1777         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1778         vertstrings_count += shaderstaticparms_count;
1779         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1780         geomstrings_count += shaderstaticparms_count;
1781         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1782         fragstrings_count += shaderstaticparms_count;
1783
1784         // replace spaces in the cachename with _ characters
1785         for (i = 0;cachename[i];i++)
1786                 if (cachename[i] == ' ')
1787                         cachename[i] = '_';
1788
1789         // now append the shader text itself
1790         vertstrings_list[vertstrings_count++] = sourcestring;
1791         geomstrings_list[geomstrings_count++] = sourcestring;
1792         fragstrings_list[fragstrings_count++] = sourcestring;
1793
1794         vertstring_length = 0;
1795         for (i = 0;i < vertstrings_count;i++)
1796                 vertstring_length += (int)strlen(vertstrings_list[i]);
1797         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1798         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1799                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1800
1801         geomstring_length = 0;
1802         for (i = 0;i < geomstrings_count;i++)
1803                 geomstring_length += (int)strlen(geomstrings_list[i]);
1804         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1805         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1806                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1807
1808         fragstring_length = 0;
1809         for (i = 0;i < fragstrings_count;i++)
1810                 fragstring_length += (int)strlen(fragstrings_list[i]);
1811         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1812         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1813                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1814
1815         // try to load the cached shader, or generate one
1816         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1817
1818         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1819                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1820         else
1821                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1822
1823         // free the strings
1824         if (vertstring)
1825                 Mem_Free(vertstring);
1826         if (geomstring)
1827                 Mem_Free(geomstring);
1828         if (fragstring)
1829                 Mem_Free(fragstring);
1830         if (sourcestring)
1831                 Mem_Free(sourcestring);
1832 }
1833
1834 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1835 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1836 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);}
1837 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);}
1838 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);}
1839 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);}
1840
1841 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1842 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1843 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);}
1844 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);}
1845 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);}
1846 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);}
1847
1848 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1849 {
1850         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1851         if (r_hlsl_permutation != perm)
1852         {
1853                 r_hlsl_permutation = perm;
1854                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1855                 {
1856                         if (!r_hlsl_permutation->compiled)
1857                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1858                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1859                         {
1860                                 // remove features until we find a valid permutation
1861                                 int i;
1862                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1863                                 {
1864                                         // reduce i more quickly whenever it would not remove any bits
1865                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1866                                         if (!(permutation & j))
1867                                                 continue;
1868                                         permutation -= j;
1869                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1870                                         if (!r_hlsl_permutation->compiled)
1871                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1872                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1873                                                 break;
1874                                 }
1875                                 if (i >= SHADERPERMUTATION_COUNT)
1876                                 {
1877                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1878                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1879                                         return; // no bit left to clear, entire mode is broken
1880                                 }
1881                         }
1882                 }
1883                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1884                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1885         }
1886         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1887         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1888         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1889 }
1890 #endif
1891
1892 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1893 {
1894         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1895         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1896         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1897         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1898 }
1899
1900 void R_GLSL_Restart_f(void)
1901 {
1902         unsigned int i, limit;
1903         if (glslshaderstring)
1904                 Mem_Free(glslshaderstring);
1905         glslshaderstring = NULL;
1906         if (hlslshaderstring)
1907                 Mem_Free(hlslshaderstring);
1908         hlslshaderstring = NULL;
1909         switch(vid.renderpath)
1910         {
1911         case RENDERPATH_D3D9:
1912 #ifdef SUPPORTD3D
1913                 {
1914                         r_hlsl_permutation_t *p;
1915                         r_hlsl_permutation = NULL;
1916                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1917                         for (i = 0;i < limit;i++)
1918                         {
1919                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1920                                 {
1921                                         if (p->vertexshader)
1922                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1923                                         if (p->pixelshader)
1924                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1925                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1926                                 }
1927                         }
1928                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1929                 }
1930 #endif
1931                 break;
1932         case RENDERPATH_D3D10:
1933                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1934                 break;
1935         case RENDERPATH_D3D11:
1936                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1937                 break;
1938         case RENDERPATH_GL20:
1939         case RENDERPATH_GLES2:
1940                 {
1941                         r_glsl_permutation_t *p;
1942                         r_glsl_permutation = NULL;
1943                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1944                         for (i = 0;i < limit;i++)
1945                         {
1946                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1947                                 {
1948                                         GL_Backend_FreeProgram(p->program);
1949                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1950                                 }
1951                         }
1952                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1953                 }
1954                 break;
1955         case RENDERPATH_GL11:
1956         case RENDERPATH_GL13:
1957         case RENDERPATH_GLES1:
1958                 break;
1959         case RENDERPATH_SOFT:
1960                 break;
1961         }
1962 }
1963
1964 static void R_GLSL_DumpShader_f(void)
1965 {
1966         int i, language, mode, dupe;
1967         char *text;
1968         shadermodeinfo_t *modeinfo;
1969         qfile_t *file;
1970
1971         for (language = 0;language < 2;language++)
1972         {
1973                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1974                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1975                 {
1976                         // don't dump the same file multiple times (most or all shaders come from the same file)
1977                         for (dupe = mode - 1;dupe >= 0;dupe--)
1978                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1979                                         break;
1980                         if (dupe >= 0)
1981                                 continue;
1982                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1983                         if (!text)
1984                                 continue;
1985                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1986                         if (file)
1987                         {
1988                                 FS_Print(file, "/* The engine may define the following macros:\n");
1989                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1990                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1991                                         FS_Print(file, modeinfo[i].pretext);
1992                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1993                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1994                                 FS_Print(file, "*/\n");
1995                                 FS_Print(file, text);
1996                                 FS_Close(file);
1997                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1998                         }
1999                         else
2000                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2001                         Mem_Free(text);
2002                 }
2003         }
2004 }
2005
2006 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2007 {
2008         unsigned int permutation = 0;
2009         if (r_trippy.integer && !notrippy)
2010                 permutation |= SHADERPERMUTATION_TRIPPY;
2011         permutation |= SHADERPERMUTATION_VIEWTINT;
2012         if (first)
2013                 permutation |= SHADERPERMUTATION_DIFFUSE;
2014         if (second)
2015                 permutation |= SHADERPERMUTATION_SPECULAR;
2016         if (texturemode == GL_MODULATE)
2017                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2018         else if (texturemode == GL_ADD)
2019                 permutation |= SHADERPERMUTATION_GLOW;
2020         else if (texturemode == GL_DECAL)
2021                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2022         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2023                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2024         if (suppresstexalpha)
2025                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2026         if (!second)
2027                 texturemode = GL_MODULATE;
2028         if (vid.allowalphatocoverage)
2029                 GL_AlphaToCoverage(false);
2030         switch (vid.renderpath)
2031         {
2032         case RENDERPATH_D3D9:
2033 #ifdef SUPPORTD3D
2034                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2035                 R_Mesh_TexBind(GL20TU_FIRST , first );
2036                 R_Mesh_TexBind(GL20TU_SECOND, second);
2037                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2038                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2039 #endif
2040                 break;
2041         case RENDERPATH_D3D10:
2042                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2043                 break;
2044         case RENDERPATH_D3D11:
2045                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2046                 break;
2047         case RENDERPATH_GL20:
2048         case RENDERPATH_GLES2:
2049                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2050                 if (r_glsl_permutation->tex_Texture_First >= 0)
2051                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2052                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2053                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2054                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2055                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2056                 break;
2057         case RENDERPATH_GL13:
2058         case RENDERPATH_GLES1:
2059                 R_Mesh_TexBind(0, first );
2060                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2061                 R_Mesh_TexMatrix(0, NULL);
2062                 R_Mesh_TexBind(1, second);
2063                 if (second)
2064                 {
2065                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2066                         R_Mesh_TexMatrix(1, NULL);
2067                 }
2068                 break;
2069         case RENDERPATH_GL11:
2070                 R_Mesh_TexBind(0, first );
2071                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2072                 R_Mesh_TexMatrix(0, NULL);
2073                 break;
2074         case RENDERPATH_SOFT:
2075                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2076                 R_Mesh_TexBind(GL20TU_FIRST , first );
2077                 R_Mesh_TexBind(GL20TU_SECOND, second);
2078                 break;
2079         }
2080 }
2081
2082 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2083 {
2084         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2085 }
2086
2087 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2088 {
2089         unsigned int permutation = 0;
2090         if (r_trippy.integer && !notrippy)
2091                 permutation |= SHADERPERMUTATION_TRIPPY;
2092         if (depthrgb)
2093                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2094         if (skeletal)
2095                 permutation |= SHADERPERMUTATION_SKELETAL;
2096
2097         if (vid.allowalphatocoverage)
2098                 GL_AlphaToCoverage(false);
2099         switch (vid.renderpath)
2100         {
2101         case RENDERPATH_D3D9:
2102 #ifdef SUPPORTD3D
2103                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2104 #endif
2105                 break;
2106         case RENDERPATH_D3D10:
2107                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2108                 break;
2109         case RENDERPATH_D3D11:
2110                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2111                 break;
2112         case RENDERPATH_GL20:
2113         case RENDERPATH_GLES2:
2114                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2115 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2116                 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);
2117 #endif
2118                 break;
2119         case RENDERPATH_GL13:
2120         case RENDERPATH_GLES1:
2121                 R_Mesh_TexBind(0, 0);
2122                 R_Mesh_TexBind(1, 0);
2123                 break;
2124         case RENDERPATH_GL11:
2125                 R_Mesh_TexBind(0, 0);
2126                 break;
2127         case RENDERPATH_SOFT:
2128                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2129                 break;
2130         }
2131 }
2132
2133 extern qboolean r_shadow_usingdeferredprepass;
2134 extern rtexture_t *r_shadow_attenuationgradienttexture;
2135 extern rtexture_t *r_shadow_attenuation2dtexture;
2136 extern rtexture_t *r_shadow_attenuation3dtexture;
2137 extern qboolean r_shadow_usingshadowmap2d;
2138 extern qboolean r_shadow_usingshadowmaportho;
2139 extern float r_shadow_shadowmap_texturescale[2];
2140 extern float r_shadow_shadowmap_parameters[4];
2141 extern qboolean r_shadow_shadowmapvsdct;
2142 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2143 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2144 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2145 extern matrix4x4_t r_shadow_shadowmapmatrix;
2146 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2147 extern int r_shadow_prepass_width;
2148 extern int r_shadow_prepass_height;
2149 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2150 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2151 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2152 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2153
2154 #define BLENDFUNC_ALLOWS_COLORMOD      1
2155 #define BLENDFUNC_ALLOWS_FOG           2
2156 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2157 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2158 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2159 static int R_BlendFuncFlags(int src, int dst)
2160 {
2161         int r = 0;
2162
2163         // a blendfunc allows colormod if:
2164         // a) it can never keep the destination pixel invariant, or
2165         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2166         // this is to prevent unintended side effects from colormod
2167
2168         // a blendfunc allows fog if:
2169         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2170         // this is to prevent unintended side effects from fog
2171
2172         // these checks are the output of fogeval.pl
2173
2174         r |= BLENDFUNC_ALLOWS_COLORMOD;
2175         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2176         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2177         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2178         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2179         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2181         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2182         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2183         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2184         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2185         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2186         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2187         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2188         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2189         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2190         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2191         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2193         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2194         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2195         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196
2197         return r;
2198 }
2199
2200 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)
2201 {
2202         // select a permutation of the lighting shader appropriate to this
2203         // combination of texture, entity, light source, and fogging, only use the
2204         // minimum features necessary to avoid wasting rendering time in the
2205         // fragment shader on features that are not being used
2206         unsigned int permutation = 0;
2207         unsigned int mode = 0;
2208         int blendfuncflags;
2209         static float dummy_colormod[3] = {1, 1, 1};
2210         float *colormod = rsurface.colormod;
2211         float m16f[16];
2212         matrix4x4_t tempmatrix;
2213         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2214         if (r_trippy.integer && !notrippy)
2215                 permutation |= SHADERPERMUTATION_TRIPPY;
2216         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2217                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2218         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2219                 permutation |= SHADERPERMUTATION_OCCLUDE;
2220         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2221                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2222         if (rsurfacepass == RSURFPASS_BACKGROUND)
2223         {
2224                 // distorted background
2225                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2226                 {
2227                         mode = SHADERMODE_WATER;
2228                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2229                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2230                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2231                         {
2232                                 // this is the right thing to do for wateralpha
2233                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2234                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2235                         }
2236                         else
2237                         {
2238                                 // this is the right thing to do for entity alpha
2239                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2240                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2241                         }
2242                 }
2243                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2244                 {
2245                         mode = SHADERMODE_REFRACTION;
2246                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2247                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2248                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2249                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2250                 }
2251                 else
2252                 {
2253                         mode = SHADERMODE_GENERIC;
2254                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2255                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2256                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2257                 }
2258                 if (vid.allowalphatocoverage)
2259                         GL_AlphaToCoverage(false);
2260         }
2261         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2262         {
2263                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2264                 {
2265                         switch(rsurface.texture->offsetmapping)
2266                         {
2267                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2268                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2269                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2270                         case OFFSETMAPPING_OFF: break;
2271                         }
2272                 }
2273                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2274                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2275                 // normalmap (deferred prepass), may use alpha test on diffuse
2276                 mode = SHADERMODE_DEFERREDGEOMETRY;
2277                 GL_BlendFunc(GL_ONE, GL_ZERO);
2278                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2279                 if (vid.allowalphatocoverage)
2280                         GL_AlphaToCoverage(false);
2281         }
2282         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2283         {
2284                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2285                 {
2286                         switch(rsurface.texture->offsetmapping)
2287                         {
2288                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2289                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2291                         case OFFSETMAPPING_OFF: break;
2292                         }
2293                 }
2294                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2295                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2296                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2297                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2298                 // light source
2299                 mode = SHADERMODE_LIGHTSOURCE;
2300                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2301                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2302                 if (diffusescale > 0)
2303                         permutation |= SHADERPERMUTATION_DIFFUSE;
2304                 if (specularscale > 0)
2305                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2306                 if (r_refdef.fogenabled)
2307                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2308                 if (rsurface.texture->colormapping)
2309                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2310                 if (r_shadow_usingshadowmap2d)
2311                 {
2312                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2313                         if(r_shadow_shadowmapvsdct)
2314                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2315
2316                         if (r_shadow_shadowmap2ddepthbuffer)
2317                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2318                 }
2319                 if (rsurface.texture->reflectmasktexture)
2320                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2321                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2322                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2323                 if (vid.allowalphatocoverage)
2324                         GL_AlphaToCoverage(false);
2325         }
2326         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2327         {
2328                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2329                 {
2330                         switch(rsurface.texture->offsetmapping)
2331                         {
2332                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2333                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2334                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2335                         case OFFSETMAPPING_OFF: break;
2336                         }
2337                 }
2338                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2339                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2340                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2341                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2342                 // unshaded geometry (fullbright or ambient model lighting)
2343                 mode = SHADERMODE_FLATCOLOR;
2344                 ambientscale = diffusescale = specularscale = 0;
2345                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2346                         permutation |= SHADERPERMUTATION_GLOW;
2347                 if (r_refdef.fogenabled)
2348                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2349                 if (rsurface.texture->colormapping)
2350                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2351                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2352                 {
2353                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2354                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2355
2356                         if (r_shadow_shadowmap2ddepthbuffer)
2357                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2358                 }
2359                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2360                         permutation |= SHADERPERMUTATION_REFLECTION;
2361                 if (rsurface.texture->reflectmasktexture)
2362                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2363                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2364                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2365                 // when using alphatocoverage, we don't need alphakill
2366                 if (vid.allowalphatocoverage)
2367                 {
2368                         if (r_transparent_alphatocoverage.integer)
2369                         {
2370                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2371                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2372                         }
2373                         else
2374                                 GL_AlphaToCoverage(false);
2375                 }
2376         }
2377         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2378         {
2379                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2380                 {
2381                         switch(rsurface.texture->offsetmapping)
2382                         {
2383                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2384                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2385                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2386                         case OFFSETMAPPING_OFF: break;
2387                         }
2388                 }
2389                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2390                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2391                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2392                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2393                 // directional model lighting
2394                 mode = SHADERMODE_LIGHTDIRECTION;
2395                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2396                         permutation |= SHADERPERMUTATION_GLOW;
2397                 permutation |= SHADERPERMUTATION_DIFFUSE;
2398                 if (specularscale > 0)
2399                         permutation |= SHADERPERMUTATION_SPECULAR;
2400                 if (r_refdef.fogenabled)
2401                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2402                 if (rsurface.texture->colormapping)
2403                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2404                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2405                 {
2406                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2407                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2408
2409                         if (r_shadow_shadowmap2ddepthbuffer)
2410                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2411                 }
2412                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2413                         permutation |= SHADERPERMUTATION_REFLECTION;
2414                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2415                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2416                 if (rsurface.texture->reflectmasktexture)
2417                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2418                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2419                 {
2420                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2421                         if (r_shadow_bouncegriddirectional)
2422                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2423                 }
2424                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2425                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2426                 // when using alphatocoverage, we don't need alphakill
2427                 if (vid.allowalphatocoverage)
2428                 {
2429                         if (r_transparent_alphatocoverage.integer)
2430                         {
2431                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2432                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2433                         }
2434                         else
2435                                 GL_AlphaToCoverage(false);
2436                 }
2437         }
2438         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2439         {
2440                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2441                 {
2442                         switch(rsurface.texture->offsetmapping)
2443                         {
2444                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2445                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2446                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2447                         case OFFSETMAPPING_OFF: break;
2448                         }
2449                 }
2450                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2451                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2452                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2453                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2454                 // ambient model lighting
2455                 mode = SHADERMODE_LIGHTDIRECTION;
2456                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2457                         permutation |= SHADERPERMUTATION_GLOW;
2458                 if (r_refdef.fogenabled)
2459                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2460                 if (rsurface.texture->colormapping)
2461                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2462                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2463                 {
2464                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2465                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2466
2467                         if (r_shadow_shadowmap2ddepthbuffer)
2468                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2469                 }
2470                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2471                         permutation |= SHADERPERMUTATION_REFLECTION;
2472                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2473                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2474                 if (rsurface.texture->reflectmasktexture)
2475                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2476                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2477                 {
2478                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2479                         if (r_shadow_bouncegriddirectional)
2480                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2481                 }
2482                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2483                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2484                 // when using alphatocoverage, we don't need alphakill
2485                 if (vid.allowalphatocoverage)
2486                 {
2487                         if (r_transparent_alphatocoverage.integer)
2488                         {
2489                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2490                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2491                         }
2492                         else
2493                                 GL_AlphaToCoverage(false);
2494                 }
2495         }
2496         else
2497         {
2498                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2499                 {
2500                         switch(rsurface.texture->offsetmapping)
2501                         {
2502                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2503                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2504                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2505                         case OFFSETMAPPING_OFF: break;
2506                         }
2507                 }
2508                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2509                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2510                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2511                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2512                 // lightmapped wall
2513                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2514                         permutation |= SHADERPERMUTATION_GLOW;
2515                 if (r_refdef.fogenabled)
2516                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2517                 if (rsurface.texture->colormapping)
2518                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2519                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2520                 {
2521                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2522                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2523
2524                         if (r_shadow_shadowmap2ddepthbuffer)
2525                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2526                 }
2527                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2528                         permutation |= SHADERPERMUTATION_REFLECTION;
2529                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2530                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2531                 if (rsurface.texture->reflectmasktexture)
2532                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2533                 if (FAKELIGHT_ENABLED)
2534                 {
2535                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2536                         mode = SHADERMODE_FAKELIGHT;
2537                         permutation |= SHADERPERMUTATION_DIFFUSE;
2538                         if (specularscale > 0)
2539                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2540                 }
2541                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2542                 {
2543                         // deluxemapping (light direction texture)
2544                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2545                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2546                         else
2547                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2548                         permutation |= SHADERPERMUTATION_DIFFUSE;
2549                         if (specularscale > 0)
2550                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2551                 }
2552                 else if (r_glsl_deluxemapping.integer >= 2)
2553                 {
2554                         // fake deluxemapping (uniform light direction in tangentspace)
2555                         if (rsurface.uselightmaptexture)
2556                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2557                         else
2558                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2559                         permutation |= SHADERPERMUTATION_DIFFUSE;
2560                         if (specularscale > 0)
2561                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2562                 }
2563                 else if (rsurface.uselightmaptexture)
2564                 {
2565                         // ordinary lightmapping (q1bsp, q3bsp)
2566                         mode = SHADERMODE_LIGHTMAP;
2567                 }
2568                 else
2569                 {
2570                         // ordinary vertex coloring (q3bsp)
2571                         mode = SHADERMODE_VERTEXCOLOR;
2572                 }
2573                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2574                 {
2575                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2576                         if (r_shadow_bouncegriddirectional)
2577                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2578                 }
2579                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2580                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2581                 // when using alphatocoverage, we don't need alphakill
2582                 if (vid.allowalphatocoverage)
2583                 {
2584                         if (r_transparent_alphatocoverage.integer)
2585                         {
2586                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2587                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2588                         }
2589                         else
2590                                 GL_AlphaToCoverage(false);
2591                 }
2592         }
2593         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2594                 colormod = dummy_colormod;
2595         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2596                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2597         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2598                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2599         switch(vid.renderpath)
2600         {
2601         case RENDERPATH_D3D9:
2602 #ifdef SUPPORTD3D
2603                 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);
2604                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2605                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2606                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2607                 if (mode == SHADERMODE_LIGHTSOURCE)
2608                 {
2609                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2610                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2611                 }
2612                 else
2613                 {
2614                         if (mode == SHADERMODE_LIGHTDIRECTION)
2615                         {
2616                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2617                         }
2618                 }
2619                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2620                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2621                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2622                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2623                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2624
2625                 if (mode == SHADERMODE_LIGHTSOURCE)
2626                 {
2627                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2628                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2629                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2630                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2631                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2632
2633                         // additive passes are only darkened by fog, not tinted
2634                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2635                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2636                 }
2637                 else
2638                 {
2639                         if (mode == SHADERMODE_FLATCOLOR)
2640                         {
2641                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2642                         }
2643                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2644                         {
2645                                 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]);
2646                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2647                                 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);
2648                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2649                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2650                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2651                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2652                         }
2653                         else
2654                         {
2655                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2656                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2657                                 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);
2658                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2659                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2660                         }
2661                         // additive passes are only darkened by fog, not tinted
2662                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2663                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2664                         else
2665                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2666                         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);
2667                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2668                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2669                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2670                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2671                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2672                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2673                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2674                         if (mode == SHADERMODE_WATER)
2675                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2676                 }
2677                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2678                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2679                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2680                 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));
2681                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2682                 if (rsurface.texture->pantstexture)
2683                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2684                 else
2685                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2686                 if (rsurface.texture->shirttexture)
2687                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2688                 else
2689                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2690                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2691                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2692                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2693                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2694                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2695                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2696                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2697                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2698                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2699                         );
2700                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2701                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2702                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2703                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2704
2705                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2706                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2707                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2708                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2709                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2710                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2711                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2712                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2713                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2714                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2715                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2716                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2717                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2718                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2719                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2720                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2721                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2722                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2723                 {
2724                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2725                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2726                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2727                 }
2728                 else
2729                 {
2730                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2731                 }
2732 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2733                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2734                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2735                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2736                 {
2737                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2738                         if (rsurface.rtlight)
2739                         {
2740                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2741                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2742                         }
2743                 }
2744 #endif
2745                 break;
2746         case RENDERPATH_D3D10:
2747                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2748                 break;
2749         case RENDERPATH_D3D11:
2750                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2751                 break;
2752         case RENDERPATH_GL20:
2753         case RENDERPATH_GLES2:
2754                 if (!vid.useinterleavedarrays)
2755                 {
2756                         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);
2757                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2758                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2759                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2760                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2761                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2762                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2763                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2764                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2765                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2766                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2767                 }
2768                 else
2769                 {
2770                         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);
2771                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2772                 }
2773                 // this has to be after RSurf_PrepareVerticesForBatch
2774                 if (rsurface.batchskeletaltransform3x4buffer)
2775                         permutation |= SHADERPERMUTATION_SKELETAL;
2776                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2777 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2778                 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);
2779 #endif
2780                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2781                 if (mode == SHADERMODE_LIGHTSOURCE)
2782                 {
2783                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2784                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2785                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2786                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2787                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2788                         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);
2789         
2790                         // additive passes are only darkened by fog, not tinted
2791                         if (r_glsl_permutation->loc_FogColor >= 0)
2792                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2793                         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);
2794                 }
2795                 else
2796                 {
2797                         if (mode == SHADERMODE_FLATCOLOR)
2798                         {
2799                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2800                         }
2801                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2802                         {
2803                                 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]);
2804                                 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]);
2805                                 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);
2806                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2807                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2808                                 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]);
2809                                 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]);
2810                         }
2811                         else
2812                         {
2813                                 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]);
2814                                 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]);
2815                                 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);
2816                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2817                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2818                         }
2819                         // additive passes are only darkened by fog, not tinted
2820                         if (r_glsl_permutation->loc_FogColor >= 0)
2821                         {
2822                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2823                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2824                                 else
2825                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2826                         }
2827                         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);
2828                         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]);
2829                         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]);
2830                         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]);
2831                         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]);
2832                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2833                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2834                         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);
2835                         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]);
2836                 }
2837                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2838                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2839                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2840                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2841                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2842
2843                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2844                 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));
2845                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2846                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2847                 {
2848                         if (rsurface.texture->pantstexture)
2849                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2850                         else
2851                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2852                 }
2853                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2854                 {
2855                         if (rsurface.texture->shirttexture)
2856                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2857                         else
2858                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2859                 }
2860                 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]);
2861                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2862                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2863                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2864                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2865                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2866                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2867                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2868                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2869                         );
2870                 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);
2871                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2872                 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]);
2873                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2874                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2875                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2876
2877                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2878                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2879                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2880                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2881                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2882                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2883                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2884                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2885                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2886                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2887                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2888                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2889                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2890                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2891                 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);
2892                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2893                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2894                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2895                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2896                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2897                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2898                 {
2899                         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);
2900                         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);
2901                         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);
2902                 }
2903                 else
2904                 {
2905                         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);
2906                 }
2907                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2908                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2909                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2910                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2911                 {
2912                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2913                         if (rsurface.rtlight)
2914                         {
2915                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2916                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2917                         }
2918                 }
2919                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2920                 CHECKGLERROR
2921                 break;
2922         case RENDERPATH_GL11:
2923         case RENDERPATH_GL13:
2924         case RENDERPATH_GLES1:
2925                 break;
2926         case RENDERPATH_SOFT:
2927                 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);
2928                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2929                 R_SetupShader_SetPermutationSoft(mode, permutation);
2930                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2931                 if (mode == SHADERMODE_LIGHTSOURCE)
2932                 {
2933                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2934                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2935                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2936                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2937                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2938                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2939         
2940                         // additive passes are only darkened by fog, not tinted
2941                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2942                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2943                 }
2944                 else
2945                 {
2946                         if (mode == SHADERMODE_FLATCOLOR)
2947                         {
2948                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2949                         }
2950                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2951                         {
2952                                 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]);
2953                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2954                                 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);
2955                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2956                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2957                                 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]);
2958                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2959                         }
2960                         else
2961                         {
2962                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2963                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2964                                 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);
2965                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2966                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2967                         }
2968                         // additive passes are only darkened by fog, not tinted
2969                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2970                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2971                         else
2972                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2973                         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);
2974                         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]);
2975                         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]);
2976                         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]);
2977                         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]);
2978                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2979                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2980                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2981                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2982                 }
2983                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2984                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2985                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2986                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2987                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2988
2989                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2990                 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));
2991                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2992                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2993                 {
2994                         if (rsurface.texture->pantstexture)
2995                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2996                         else
2997                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2998                 }
2999                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3000                 {
3001                         if (rsurface.texture->shirttexture)
3002                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3003                         else
3004                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3005                 }
3006                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3007                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3008                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3009                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3010                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3011                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3012                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3013                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3014                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3015                         );
3016                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3017                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3018                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3019                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3020
3021                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3022                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3023                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3024                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3025                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3026                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3027                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3028                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3029                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3030                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3031                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3032                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3033                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3034                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3035                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3036                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3037                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3038                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3039                 {
3040                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3041                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3042                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3043                 }
3044                 else
3045                 {
3046                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3047                 }
3048 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3049                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3050                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3051                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3052                 {
3053                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3054                         if (rsurface.rtlight)
3055                         {
3056                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3057                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3058                         }
3059                 }
3060                 break;
3061         }
3062 }
3063
3064 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3065 {
3066         // select a permutation of the lighting shader appropriate to this
3067         // combination of texture, entity, light source, and fogging, only use the
3068         // minimum features necessary to avoid wasting rendering time in the
3069         // fragment shader on features that are not being used
3070         unsigned int permutation = 0;
3071         unsigned int mode = 0;
3072         const float *lightcolorbase = rtlight->currentcolor;
3073         float ambientscale = rtlight->ambientscale;
3074         float diffusescale = rtlight->diffusescale;
3075         float specularscale = rtlight->specularscale;
3076         // this is the location of the light in view space
3077         vec3_t viewlightorigin;
3078         // this transforms from view space (camera) to light space (cubemap)
3079         matrix4x4_t viewtolight;
3080         matrix4x4_t lighttoview;
3081         float viewtolight16f[16];
3082         // light source
3083         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3084         if (rtlight->currentcubemap != r_texture_whitecube)
3085                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3086         if (diffusescale > 0)
3087                 permutation |= SHADERPERMUTATION_DIFFUSE;
3088         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3089                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3090         if (r_shadow_usingshadowmap2d)
3091         {
3092                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3093                 if (r_shadow_shadowmapvsdct)
3094                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3095
3096                 if (r_shadow_shadowmap2ddepthbuffer)
3097                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3098         }
3099         if (vid.allowalphatocoverage)
3100                 GL_AlphaToCoverage(false);
3101         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3102         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3103         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3104         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3105         switch(vid.renderpath)
3106         {
3107         case RENDERPATH_D3D9:
3108 #ifdef SUPPORTD3D
3109                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3110                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3111                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3112                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3113                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3114                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3115                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3116                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3117                 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);
3118                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3119                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3120
3121                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3122                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3123                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3124                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3125                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3126 #endif
3127                 break;
3128         case RENDERPATH_D3D10:
3129                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3130                 break;
3131         case RENDERPATH_D3D11:
3132                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3133                 break;
3134         case RENDERPATH_GL20:
3135         case RENDERPATH_GLES2:
3136                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3137                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3138                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3139                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3140                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3141                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3142                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3143                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3144                 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);
3145                 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]);
3146                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3147
3148                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3149                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3150                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3151                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3152                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3153                 break;
3154         case RENDERPATH_GL11:
3155         case RENDERPATH_GL13:
3156         case RENDERPATH_GLES1:
3157                 break;
3158         case RENDERPATH_SOFT:
3159                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3160                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3161                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3162                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3163                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3164                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3165                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3166                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3167                 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);
3168                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3169                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3170
3171                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3172                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3173                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3174                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3175                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3176                 break;
3177         }
3178 }
3179
3180 #define SKINFRAME_HASH 1024
3181
3182 typedef struct
3183 {
3184         unsigned int loadsequence; // incremented each level change
3185         memexpandablearray_t array;
3186         skinframe_t *hash[SKINFRAME_HASH];
3187 }
3188 r_skinframe_t;
3189 r_skinframe_t r_skinframe;
3190
3191 void R_SkinFrame_PrepareForPurge(void)
3192 {
3193         r_skinframe.loadsequence++;
3194         // wrap it without hitting zero
3195         if (r_skinframe.loadsequence >= 200)
3196                 r_skinframe.loadsequence = 1;
3197 }
3198
3199 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3200 {
3201         if (!skinframe)
3202                 return;
3203         // mark the skinframe as used for the purging code
3204         skinframe->loadsequence = r_skinframe.loadsequence;
3205 }
3206
3207 void R_SkinFrame_Purge(void)
3208 {
3209         int i;
3210         skinframe_t *s;
3211         for (i = 0;i < SKINFRAME_HASH;i++)
3212         {
3213                 for (s = r_skinframe.hash[i];s;s = s->next)
3214                 {
3215                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3216                         {
3217                                 if (s->merged == s->base)
3218                                         s->merged = NULL;
3219                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3220                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3221                                 R_PurgeTexture(s->merged);s->merged = NULL;
3222                                 R_PurgeTexture(s->base  );s->base   = NULL;
3223                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3224                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3225                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3226                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3227                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3228                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3229                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3230                                 s->loadsequence = 0;
3231                         }
3232                 }
3233         }
3234 }
3235
3236 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3237         skinframe_t *item;
3238         char basename[MAX_QPATH];
3239
3240         Image_StripImageExtension(name, basename, sizeof(basename));
3241
3242         if( last == NULL ) {
3243                 int hashindex;
3244                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3245                 item = r_skinframe.hash[hashindex];
3246         } else {
3247                 item = last->next;
3248         }
3249
3250         // linearly search through the hash bucket
3251         for( ; item ; item = item->next ) {
3252                 if( !strcmp( item->basename, basename ) ) {
3253                         return item;
3254                 }
3255         }
3256         return NULL;
3257 }
3258
3259 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3260 {
3261         skinframe_t *item;
3262         int hashindex;
3263         char basename[MAX_QPATH];
3264
3265         Image_StripImageExtension(name, basename, sizeof(basename));
3266
3267         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3268         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3269                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3270                         break;
3271
3272         if (!item) {
3273                 rtexture_t *dyntexture;
3274                 // check whether its a dynamic texture
3275                 dyntexture = CL_GetDynTexture( basename );
3276                 if (!add && !dyntexture)
3277                         return NULL;
3278                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3279                 memset(item, 0, sizeof(*item));
3280                 strlcpy(item->basename, basename, sizeof(item->basename));
3281                 item->base = dyntexture; // either NULL or dyntexture handle
3282                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3283                 item->comparewidth = comparewidth;
3284                 item->compareheight = compareheight;
3285                 item->comparecrc = comparecrc;
3286                 item->next = r_skinframe.hash[hashindex];
3287                 r_skinframe.hash[hashindex] = item;
3288         }
3289         else if (textureflags & TEXF_FORCE_RELOAD)
3290         {
3291                 rtexture_t *dyntexture;
3292                 // check whether its a dynamic texture
3293                 dyntexture = CL_GetDynTexture( basename );
3294                 if (!add && !dyntexture)
3295                         return NULL;
3296                 if (item->merged == item->base)
3297                         item->merged = NULL;
3298                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3299                 R_PurgeTexture(item->stain );item->stain  = NULL;
3300                 R_PurgeTexture(item->merged);item->merged = NULL;
3301                 R_PurgeTexture(item->base  );item->base   = NULL;
3302                 R_PurgeTexture(item->pants );item->pants  = NULL;
3303                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3304                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3305                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3306                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3307                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3308         R_PurgeTexture(item->reflect);item->reflect = NULL;
3309                 item->loadsequence = 0;
3310         }
3311         else if( item->base == NULL )
3312         {
3313                 rtexture_t *dyntexture;
3314                 // check whether its a dynamic texture
3315                 // 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]
3316                 dyntexture = CL_GetDynTexture( basename );
3317                 item->base = dyntexture; // either NULL or dyntexture handle
3318         }
3319
3320         R_SkinFrame_MarkUsed(item);
3321         return item;
3322 }
3323
3324 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3325         { \
3326                 unsigned long long avgcolor[5], wsum; \
3327                 int pix, comp, w; \
3328                 avgcolor[0] = 0; \
3329                 avgcolor[1] = 0; \
3330                 avgcolor[2] = 0; \
3331                 avgcolor[3] = 0; \
3332                 avgcolor[4] = 0; \
3333                 wsum = 0; \
3334                 for(pix = 0; pix < cnt; ++pix) \
3335                 { \
3336                         w = 0; \
3337                         for(comp = 0; comp < 3; ++comp) \
3338                                 w += getpixel; \
3339                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3340                         { \
3341                                 ++wsum; \
3342                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3343                                 w = getpixel; \
3344                                 for(comp = 0; comp < 3; ++comp) \
3345                                         avgcolor[comp] += getpixel * w; \
3346                                 avgcolor[3] += w; \
3347                         } \
3348                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3349                         avgcolor[4] += getpixel; \
3350                 } \
3351                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3352                         avgcolor[3] = 1; \
3353                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3354                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3355                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3356                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3357         }
3358
3359 extern cvar_t gl_picmip;
3360 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3361 {
3362         int j;
3363         unsigned char *pixels;
3364         unsigned char *bumppixels;
3365         unsigned char *basepixels = NULL;
3366         int basepixels_width = 0;
3367         int basepixels_height = 0;
3368         skinframe_t *skinframe;
3369         rtexture_t *ddsbase = NULL;
3370         qboolean ddshasalpha = false;
3371         float ddsavgcolor[4];
3372         char basename[MAX_QPATH];
3373         int miplevel = R_PicmipForFlags(textureflags);
3374         int savemiplevel = miplevel;
3375         int mymiplevel;
3376         char vabuf[1024];
3377
3378         if (cls.state == ca_dedicated)
3379                 return NULL;
3380
3381         // return an existing skinframe if already loaded
3382         // if loading of the first image fails, don't make a new skinframe as it
3383         // would cause all future lookups of this to be missing
3384         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3385         if (skinframe && skinframe->base)
3386                 return skinframe;
3387
3388         Image_StripImageExtension(name, basename, sizeof(basename));
3389
3390         // check for DDS texture file first
3391         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3392         {
3393                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3394                 if (basepixels == NULL)
3395                         return NULL;
3396         }
3397
3398         // FIXME handle miplevel
3399
3400         if (developer_loading.integer)
3401                 Con_Printf("loading skin \"%s\"\n", name);
3402
3403         // we've got some pixels to store, so really allocate this new texture now
3404         if (!skinframe)
3405                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3406         textureflags &= ~TEXF_FORCE_RELOAD;
3407         skinframe->stain = NULL;
3408         skinframe->merged = NULL;
3409         skinframe->base = NULL;
3410         skinframe->pants = NULL;
3411         skinframe->shirt = NULL;
3412         skinframe->nmap = NULL;
3413         skinframe->gloss = NULL;
3414         skinframe->glow = NULL;
3415         skinframe->fog = NULL;
3416         skinframe->reflect = NULL;
3417         skinframe->hasalpha = false;
3418         // we could store the q2animname here too
3419
3420         if (ddsbase)
3421         {
3422                 skinframe->base = ddsbase;
3423                 skinframe->hasalpha = ddshasalpha;
3424                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3425                 if (r_loadfog && skinframe->hasalpha)
3426                         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);
3427                 //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]);
3428         }
3429         else
3430         {
3431                 basepixels_width = image_width;
3432                 basepixels_height = image_height;
3433                 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);
3434                 if (textureflags & TEXF_ALPHA)
3435                 {
3436                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3437                         {
3438                                 if (basepixels[j] < 255)
3439                                 {
3440                                         skinframe->hasalpha = true;
3441                                         break;
3442                                 }
3443                         }
3444                         if (r_loadfog && skinframe->hasalpha)
3445                         {
3446                                 // has transparent pixels
3447                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3448                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3449                                 {
3450                                         pixels[j+0] = 255;
3451                                         pixels[j+1] = 255;
3452                                         pixels[j+2] = 255;
3453                                         pixels[j+3] = basepixels[j+3];
3454                                 }
3455                                 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);
3456                                 Mem_Free(pixels);
3457                         }
3458                 }
3459                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3460 #ifndef USE_GLES2
3461                 //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]);
3462                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3463                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3464                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3465                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3466 #endif
3467         }
3468
3469         if (r_loaddds)
3470         {
3471                 mymiplevel = savemiplevel;
3472                 if (r_loadnormalmap)
3473                         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);
3474                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3475                 if (r_loadgloss)
3476                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3477                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3478                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3479                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3480         }
3481
3482         // _norm is the name used by tenebrae and has been adopted as standard
3483         if (r_loadnormalmap && skinframe->nmap == NULL)
3484         {
3485                 mymiplevel = savemiplevel;
3486                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3487                 {
3488                         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);
3489                         Mem_Free(pixels);
3490                         pixels = NULL;
3491                 }
3492                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3493                 {
3494                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3495                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3496                         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);
3497                         Mem_Free(pixels);
3498                         Mem_Free(bumppixels);
3499                 }
3500                 else if (r_shadow_bumpscale_basetexture.value > 0)
3501                 {
3502                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3503                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3504                         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);
3505                         Mem_Free(pixels);
3506                 }
3507 #ifndef USE_GLES2
3508                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3509                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3510 #endif
3511         }
3512
3513         // _luma is supported only for tenebrae compatibility
3514         // _glow is the preferred name
3515         mymiplevel = savemiplevel;
3516         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))))
3517         {
3518                 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);
3519 #ifndef USE_GLES2
3520                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3521                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3522 #endif
3523                 Mem_Free(pixels);pixels = NULL;
3524         }
3525
3526         mymiplevel = savemiplevel;
3527         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3528         {
3529                 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);
3530 #ifndef USE_GLES2
3531                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3532                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3533 #endif
3534                 Mem_Free(pixels);
3535                 pixels = NULL;
3536         }
3537
3538         mymiplevel = savemiplevel;
3539         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3540         {
3541                 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);
3542 #ifndef USE_GLES2
3543                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3544                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3545 #endif
3546                 Mem_Free(pixels);
3547                 pixels = NULL;
3548         }
3549
3550         mymiplevel = savemiplevel;
3551         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3552         {
3553                 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);
3554 #ifndef USE_GLES2
3555                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3556                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3557 #endif
3558                 Mem_Free(pixels);
3559                 pixels = NULL;
3560         }
3561
3562         mymiplevel = savemiplevel;
3563         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3564         {
3565                 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);
3566 #ifndef USE_GLES2
3567                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3568                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3569 #endif
3570                 Mem_Free(pixels);
3571                 pixels = NULL;
3572         }
3573
3574         if (basepixels)
3575                 Mem_Free(basepixels);
3576
3577         return skinframe;
3578 }
3579
3580 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3581 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3582 {
3583         int i;
3584         unsigned char *temp1, *temp2;
3585         skinframe_t *skinframe;
3586         char vabuf[1024];
3587
3588         if (cls.state == ca_dedicated)
3589                 return NULL;
3590
3591         // if already loaded just return it, otherwise make a new skinframe
3592         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3593         if (skinframe->base)
3594                 return skinframe;
3595         textureflags &= ~TEXF_FORCE_RELOAD;
3596
3597         skinframe->stain = NULL;
3598         skinframe->merged = NULL;
3599         skinframe->base = NULL;
3600         skinframe->pants = NULL;
3601         skinframe->shirt = NULL;
3602         skinframe->nmap = NULL;
3603         skinframe->gloss = NULL;
3604         skinframe->glow = NULL;
3605         skinframe->fog = NULL;
3606         skinframe->reflect = NULL;
3607         skinframe->hasalpha = false;
3608
3609         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3610         if (!skindata)
3611                 return NULL;
3612
3613         if (developer_loading.integer)
3614                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3615
3616         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3617         {
3618                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3619                 temp2 = temp1 + width * height * 4;
3620                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3621                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3622                 Mem_Free(temp1);
3623         }
3624         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3625         if (textureflags & TEXF_ALPHA)
3626         {
3627                 for (i = 3;i < width * height * 4;i += 4)
3628                 {
3629                         if (skindata[i] < 255)
3630                         {
3631                                 skinframe->hasalpha = true;
3632                                 break;
3633                         }
3634                 }
3635                 if (r_loadfog && skinframe->hasalpha)
3636                 {
3637                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3638                         memcpy(fogpixels, skindata, width * height * 4);
3639                         for (i = 0;i < width * height * 4;i += 4)
3640                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3641                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3642                         Mem_Free(fogpixels);
3643                 }
3644         }
3645
3646         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3647         //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]);
3648
3649         return skinframe;
3650 }
3651
3652 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3653 {
3654         int i;
3655         int featuresmask;
3656         skinframe_t *skinframe;
3657
3658         if (cls.state == ca_dedicated)
3659                 return NULL;
3660
3661         // if already loaded just return it, otherwise make a new skinframe
3662         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3663         if (skinframe->base)
3664                 return skinframe;
3665         //textureflags &= ~TEXF_FORCE_RELOAD;
3666
3667         skinframe->stain = NULL;
3668         skinframe->merged = NULL;
3669         skinframe->base = NULL;
3670         skinframe->pants = NULL;
3671         skinframe->shirt = NULL;
3672         skinframe->nmap = NULL;
3673         skinframe->gloss = NULL;
3674         skinframe->glow = NULL;
3675         skinframe->fog = NULL;
3676         skinframe->reflect = NULL;
3677         skinframe->hasalpha = false;
3678
3679         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3680         if (!skindata)
3681                 return NULL;
3682
3683         if (developer_loading.integer)
3684                 Con_Printf("loading quake skin \"%s\"\n", name);
3685
3686         // 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)
3687         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3688         memcpy(skinframe->qpixels, skindata, width*height);
3689         skinframe->qwidth = width;
3690         skinframe->qheight = height;
3691
3692         featuresmask = 0;
3693         for (i = 0;i < width * height;i++)
3694                 featuresmask |= palette_featureflags[skindata[i]];
3695
3696         skinframe->hasalpha = false;
3697         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3698         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3699         skinframe->qgeneratemerged = true;
3700         skinframe->qgeneratebase = skinframe->qhascolormapping;
3701         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3702
3703         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3704         //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]);
3705
3706         return skinframe;
3707 }
3708
3709 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3710 {
3711         int width;
3712         int height;
3713         unsigned char *skindata;
3714         char vabuf[1024];
3715
3716         if (!skinframe->qpixels)
3717                 return;
3718
3719         if (!skinframe->qhascolormapping)
3720                 colormapped = false;
3721
3722         if (colormapped)
3723         {
3724                 if (!skinframe->qgeneratebase)
3725                         return;
3726         }
3727         else
3728         {
3729                 if (!skinframe->qgeneratemerged)
3730                         return;
3731         }
3732
3733         width = skinframe->qwidth;
3734         height = skinframe->qheight;
3735         skindata = skinframe->qpixels;
3736
3737         if (skinframe->qgeneratenmap)
3738         {
3739                 unsigned char *temp1, *temp2;
3740                 skinframe->qgeneratenmap = false;
3741                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3742                 temp2 = temp1 + width * height * 4;
3743                 // use either a custom palette or the quake palette
3744                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3745                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3746                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3747                 Mem_Free(temp1);
3748         }
3749
3750         if (skinframe->qgenerateglow)
3751         {
3752                 skinframe->qgenerateglow = false;
3753                 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
3754         }
3755
3756         if (colormapped)
3757         {
3758                 skinframe->qgeneratebase = false;
3759                 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);
3760                 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);
3761                 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);
3762         }
3763         else
3764         {
3765                 skinframe->qgeneratemerged = false;
3766                 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);
3767         }
3768
3769         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3770         {
3771                 Mem_Free(skinframe->qpixels);
3772                 skinframe->qpixels = NULL;
3773         }
3774 }
3775
3776 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)
3777 {
3778         int i;
3779         skinframe_t *skinframe;
3780         char vabuf[1024];
3781
3782         if (cls.state == ca_dedicated)
3783                 return NULL;
3784
3785         // if already loaded just return it, otherwise make a new skinframe
3786         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3787         if (skinframe->base)
3788                 return skinframe;
3789         textureflags &= ~TEXF_FORCE_RELOAD;
3790
3791         skinframe->stain = NULL;
3792         skinframe->merged = NULL;
3793         skinframe->base = NULL;
3794         skinframe->pants = NULL;
3795         skinframe->shirt = NULL;
3796         skinframe->nmap = NULL;
3797         skinframe->gloss = NULL;
3798         skinframe->glow = NULL;
3799         skinframe->fog = NULL;
3800         skinframe->reflect = NULL;
3801         skinframe->hasalpha = false;
3802
3803         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3804         if (!skindata)
3805                 return NULL;
3806
3807         if (developer_loading.integer)
3808                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3809
3810         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3811         if (textureflags & TEXF_ALPHA)
3812         {
3813                 for (i = 0;i < width * height;i++)
3814                 {
3815                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3816                         {
3817                                 skinframe->hasalpha = true;
3818                                 break;
3819                         }
3820                 }
3821                 if (r_loadfog && skinframe->hasalpha)
3822                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3823         }
3824
3825         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3826         //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]);
3827
3828         return skinframe;
3829 }
3830
3831 skinframe_t *R_SkinFrame_LoadMissing(void)
3832 {
3833         skinframe_t *skinframe;
3834
3835         if (cls.state == ca_dedicated)
3836                 return NULL;
3837
3838         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3839         skinframe->stain = NULL;
3840         skinframe->merged = NULL;
3841         skinframe->base = NULL;
3842         skinframe->pants = NULL;
3843         skinframe->shirt = NULL;
3844         skinframe->nmap = NULL;
3845         skinframe->gloss = NULL;
3846         skinframe->glow = NULL;
3847         skinframe->fog = NULL;
3848         skinframe->reflect = NULL;
3849         skinframe->hasalpha = false;
3850
3851         skinframe->avgcolor[0] = rand() / RAND_MAX;
3852         skinframe->avgcolor[1] = rand() / RAND_MAX;
3853         skinframe->avgcolor[2] = rand() / RAND_MAX;
3854         skinframe->avgcolor[3] = 1;
3855
3856         return skinframe;
3857 }
3858
3859 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3860 typedef struct suffixinfo_s
3861 {
3862         const char *suffix;
3863         qboolean flipx, flipy, flipdiagonal;
3864 }
3865 suffixinfo_t;
3866 static suffixinfo_t suffix[3][6] =
3867 {
3868         {
3869                 {"px",   false, false, false},
3870                 {"nx",   false, false, false},
3871                 {"py",   false, false, false},
3872                 {"ny",   false, false, false},
3873                 {"pz",   false, false, false},
3874                 {"nz",   false, false, false}
3875         },
3876         {
3877                 {"posx", false, false, false},
3878                 {"negx", false, false, false},
3879                 {"posy", false, false, false},
3880                 {"negy", false, false, false},
3881                 {"posz", false, false, false},
3882                 {"negz", false, false, false}
3883         },
3884         {
3885                 {"rt",    true, false,  true},
3886                 {"lf",   false,  true,  true},
3887                 {"ft",    true,  true, false},
3888                 {"bk",   false, false, false},
3889                 {"up",    true, false,  true},
3890                 {"dn",    true, false,  true}
3891         }
3892 };
3893
3894 static int componentorder[4] = {0, 1, 2, 3};
3895
3896 static rtexture_t *R_LoadCubemap(const char *basename)
3897 {
3898         int i, j, cubemapsize;
3899         unsigned char *cubemappixels, *image_buffer;
3900         rtexture_t *cubemaptexture;
3901         char name[256];
3902         // must start 0 so the first loadimagepixels has no requested width/height
3903         cubemapsize = 0;
3904         cubemappixels = NULL;
3905         cubemaptexture = NULL;
3906         // keep trying different suffix groups (posx, px, rt) until one loads
3907         for (j = 0;j < 3 && !cubemappixels;j++)
3908         {
3909                 // load the 6 images in the suffix group
3910                 for (i = 0;i < 6;i++)
3911                 {
3912                         // generate an image name based on the base and and suffix
3913                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3914                         // load it
3915                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3916                         {
3917                                 // an image loaded, make sure width and height are equal
3918                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3919                                 {
3920                                         // if this is the first image to load successfully, allocate the cubemap memory
3921                                         if (!cubemappixels && image_width >= 1)
3922                                         {
3923                                                 cubemapsize = image_width;
3924                                                 // note this clears to black, so unavailable sides are black
3925                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3926                                         }
3927                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3928                                         if (cubemappixels)
3929                                                 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);
3930                                 }
3931                                 else
3932                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3933                                 // free the image
3934                                 Mem_Free(image_buffer);
3935                         }
3936                 }
3937         }
3938         // if a cubemap loaded, upload it
3939         if (cubemappixels)
3940         {
3941                 if (developer_loading.integer)
3942                         Con_Printf("loading cubemap \"%s\"\n", basename);
3943
3944                 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);
3945                 Mem_Free(cubemappixels);
3946         }
3947         else
3948         {
3949                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3950                 if (developer_loading.integer)
3951                 {
3952                         Con_Printf("(tried tried images ");
3953                         for (j = 0;j < 3;j++)
3954                                 for (i = 0;i < 6;i++)
3955                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3956                         Con_Print(" and was unable to find any of them).\n");
3957                 }
3958         }
3959         return cubemaptexture;
3960 }
3961
3962 rtexture_t *R_GetCubemap(const char *basename)
3963 {
3964         int i;
3965         for (i = 0;i < r_texture_numcubemaps;i++)
3966                 if (r_texture_cubemaps[i] != NULL)
3967                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3968                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3969         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3970                 return r_texture_whitecube;
3971         r_texture_numcubemaps++;
3972         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3973         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3974         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3975         return r_texture_cubemaps[i]->texture;
3976 }
3977
3978 static void R_Main_FreeViewCache(void)
3979 {
3980         if (r_refdef.viewcache.entityvisible)
3981                 Mem_Free(r_refdef.viewcache.entityvisible);
3982         if (r_refdef.viewcache.world_pvsbits)
3983                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3984         if (r_refdef.viewcache.world_leafvisible)
3985                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3986         if (r_refdef.viewcache.world_surfacevisible)
3987                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3988         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3989 }
3990
3991 static void R_Main_ResizeViewCache(void)
3992 {
3993         int numentities = r_refdef.scene.numentities;
3994         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3995         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3996         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3997         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3998         if (r_refdef.viewcache.maxentities < numentities)
3999         {
4000                 r_refdef.viewcache.maxentities = numentities;
4001                 if (r_refdef.viewcache.entityvisible)
4002                         Mem_Free(r_refdef.viewcache.entityvisible);
4003                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4004         }
4005         if (r_refdef.viewcache.world_numclusters != numclusters)
4006         {
4007                 r_refdef.viewcache.world_numclusters = numclusters;
4008                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4009                 if (r_refdef.viewcache.world_pvsbits)
4010                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4011                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4012         }
4013         if (r_refdef.viewcache.world_numleafs != numleafs)
4014         {
4015                 r_refdef.viewcache.world_numleafs = numleafs;
4016                 if (r_refdef.viewcache.world_leafvisible)
4017                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4018                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4019         }
4020         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4021         {
4022                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4023                 if (r_refdef.viewcache.world_surfacevisible)
4024                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4025                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4026         }
4027 }
4028
4029 extern rtexture_t *loadingscreentexture;
4030 static void gl_main_start(void)
4031 {
4032         loadingscreentexture = NULL;
4033         r_texture_blanknormalmap = NULL;
4034         r_texture_white = NULL;
4035         r_texture_grey128 = NULL;
4036         r_texture_black = NULL;
4037         r_texture_whitecube = NULL;
4038         r_texture_normalizationcube = NULL;
4039         r_texture_fogattenuation = NULL;
4040         r_texture_fogheighttexture = NULL;
4041         r_texture_gammaramps = NULL;
4042         r_texture_numcubemaps = 0;
4043         r_uniformbufferalignment = 32;
4044
4045         r_loaddds = r_texture_dds_load.integer != 0;
4046         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4047
4048         switch(vid.renderpath)
4049         {
4050         case RENDERPATH_GL20:
4051         case RENDERPATH_D3D9:
4052         case RENDERPATH_D3D10:
4053         case RENDERPATH_D3D11:
4054         case RENDERPATH_SOFT:
4055         case RENDERPATH_GLES2:
4056                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4057                 Cvar_SetValueQuick(&gl_combine, 1);
4058                 Cvar_SetValueQuick(&r_glsl, 1);
4059                 r_loadnormalmap = true;
4060                 r_loadgloss = true;
4061                 r_loadfog = false;
4062 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4063                 if (vid.support.arb_uniform_buffer_object)
4064                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4065 #endif
4066                         break;
4067         case RENDERPATH_GL13:
4068         case RENDERPATH_GLES1:
4069                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4070                 Cvar_SetValueQuick(&gl_combine, 1);
4071                 Cvar_SetValueQuick(&r_glsl, 0);
4072                 r_loadnormalmap = false;
4073                 r_loadgloss = false;
4074                 r_loadfog = true;
4075                 break;
4076         case RENDERPATH_GL11:
4077                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4078                 Cvar_SetValueQuick(&gl_combine, 0);
4079                 Cvar_SetValueQuick(&r_glsl, 0);
4080                 r_loadnormalmap = false;
4081                 r_loadgloss = false;
4082                 r_loadfog = true;
4083                 break;
4084         }
4085
4086         R_AnimCache_Free();
4087         R_FrameData_Reset();
4088         R_BufferData_Reset();
4089
4090         r_numqueries = 0;
4091         r_maxqueries = 0;
4092         memset(r_queries, 0, sizeof(r_queries));
4093
4094         r_qwskincache = NULL;
4095         r_qwskincache_size = 0;
4096
4097         // due to caching of texture_t references, the collision cache must be reset
4098         Collision_Cache_Reset(true);
4099
4100         // set up r_skinframe loading system for textures
4101         memset(&r_skinframe, 0, sizeof(r_skinframe));
4102         r_skinframe.loadsequence = 1;
4103         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4104
4105         r_main_texturepool = R_AllocTexturePool();
4106         R_BuildBlankTextures();
4107         R_BuildNoTexture();
4108         if (vid.support.arb_texture_cube_map)
4109         {
4110                 R_BuildWhiteCube();
4111                 R_BuildNormalizationCube();
4112         }
4113         r_texture_fogattenuation = NULL;
4114         r_texture_fogheighttexture = NULL;
4115         r_texture_gammaramps = NULL;
4116         //r_texture_fogintensity = NULL;
4117         memset(&r_fb, 0, sizeof(r_fb));
4118         r_glsl_permutation = NULL;
4119         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4120         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4121         glslshaderstring = NULL;
4122 #ifdef SUPPORTD3D
4123         r_hlsl_permutation = NULL;
4124         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4125         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4126 #endif
4127         hlslshaderstring = NULL;
4128         memset(&r_svbsp, 0, sizeof (r_svbsp));
4129
4130         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4131         r_texture_numcubemaps = 0;
4132
4133         r_refdef.fogmasktable_density = 0;
4134
4135 #ifdef __ANDROID__
4136         // For Steelstorm Android
4137         // FIXME CACHE the program and reload
4138         // FIXME see possible combinations for SS:BR android
4139         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4140         R_SetupShader_SetPermutationGLSL(0, 12);
4141         R_SetupShader_SetPermutationGLSL(0, 13);
4142         R_SetupShader_SetPermutationGLSL(0, 8388621);
4143         R_SetupShader_SetPermutationGLSL(3, 0);
4144         R_SetupShader_SetPermutationGLSL(3, 2048);
4145         R_SetupShader_SetPermutationGLSL(5, 0);
4146         R_SetupShader_SetPermutationGLSL(5, 2);
4147         R_SetupShader_SetPermutationGLSL(5, 2048);
4148         R_SetupShader_SetPermutationGLSL(5, 8388608);
4149         R_SetupShader_SetPermutationGLSL(11, 1);
4150         R_SetupShader_SetPermutationGLSL(11, 2049);
4151         R_SetupShader_SetPermutationGLSL(11, 8193);
4152         R_SetupShader_SetPermutationGLSL(11, 10241);
4153         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4154 #endif
4155 }
4156
4157 static void gl_main_shutdown(void)
4158 {
4159         R_AnimCache_Free();
4160         R_FrameData_Reset();
4161         R_BufferData_Reset();
4162
4163         R_Main_FreeViewCache();
4164
4165         switch(vid.renderpath)
4166         {
4167         case RENDERPATH_GL11:
4168         case RENDERPATH_GL13:
4169         case RENDERPATH_GL20:
4170         case RENDERPATH_GLES1:
4171         case RENDERPATH_GLES2:
4172 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4173                 if (r_maxqueries)
4174                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4175 #endif
4176                 break;
4177         case RENDERPATH_D3D9:
4178                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4179                 break;
4180         case RENDERPATH_D3D10:
4181                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4182                 break;
4183         case RENDERPATH_D3D11:
4184                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4185                 break;
4186         case RENDERPATH_SOFT:
4187                 break;
4188         }
4189
4190         r_numqueries = 0;
4191         r_maxqueries = 0;
4192         memset(r_queries, 0, sizeof(r_queries));
4193
4194         r_qwskincache = NULL;
4195         r_qwskincache_size = 0;
4196
4197         // clear out the r_skinframe state
4198         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4199         memset(&r_skinframe, 0, sizeof(r_skinframe));
4200
4201         if (r_svbsp.nodes)
4202                 Mem_Free(r_svbsp.nodes);
4203         memset(&r_svbsp, 0, sizeof (r_svbsp));
4204         R_FreeTexturePool(&r_main_texturepool);
4205         loadingscreentexture = NULL;
4206         r_texture_blanknormalmap = NULL;
4207         r_texture_white = NULL;
4208         r_texture_grey128 = NULL;
4209         r_texture_black = NULL;
4210         r_texture_whitecube = NULL;
4211         r_texture_normalizationcube = NULL;
4212         r_texture_fogattenuation = NULL;
4213         r_texture_fogheighttexture = NULL;
4214         r_texture_gammaramps = NULL;
4215         r_texture_numcubemaps = 0;
4216         //r_texture_fogintensity = NULL;
4217         memset(&r_fb, 0, sizeof(r_fb));
4218         R_GLSL_Restart_f();
4219
4220         r_glsl_permutation = NULL;
4221         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4222         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4223         glslshaderstring = NULL;
4224 #ifdef SUPPORTD3D
4225         r_hlsl_permutation = NULL;
4226         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4227         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4228 #endif
4229         hlslshaderstring = NULL;
4230 }
4231
4232 static void gl_main_newmap(void)
4233 {
4234         // FIXME: move this code to client
4235         char *entities, entname[MAX_QPATH];
4236         if (r_qwskincache)
4237                 Mem_Free(r_qwskincache);
4238         r_qwskincache = NULL;
4239         r_qwskincache_size = 0;
4240         if (cl.worldmodel)
4241         {
4242                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4243                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4244                 {
4245                         CL_ParseEntityLump(entities);
4246                         Mem_Free(entities);
4247                         return;
4248                 }
4249                 if (cl.worldmodel->brush.entities)
4250                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4251         }
4252         R_Main_FreeViewCache();
4253
4254         R_FrameData_Reset();
4255         R_BufferData_Reset();
4256 }
4257
4258 void GL_Main_Init(void)
4259 {
4260         int i;
4261         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4262
4263         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4264         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4265         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4266         if (gamemode == GAME_NEHAHRA)
4267         {
4268                 Cvar_RegisterVariable (&gl_fogenable);
4269                 Cvar_RegisterVariable (&gl_fogdensity);
4270                 Cvar_RegisterVariable (&gl_fogred);
4271                 Cvar_RegisterVariable (&gl_foggreen);
4272                 Cvar_RegisterVariable (&gl_fogblue);
4273                 Cvar_RegisterVariable (&gl_fogstart);
4274                 Cvar_RegisterVariable (&gl_fogend);
4275                 Cvar_RegisterVariable (&gl_skyclip);
4276         }
4277         Cvar_RegisterVariable(&r_motionblur);
4278         Cvar_RegisterVariable(&r_damageblur);
4279         Cvar_RegisterVariable(&r_motionblur_averaging);
4280         Cvar_RegisterVariable(&r_motionblur_randomize);
4281         Cvar_RegisterVariable(&r_motionblur_minblur);
4282         Cvar_RegisterVariable(&r_motionblur_maxblur);
4283         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4284         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4285         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4286         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4287         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4288         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4289         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4290         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4291         Cvar_RegisterVariable(&r_equalize_entities_by);
4292         Cvar_RegisterVariable(&r_equalize_entities_to);
4293         Cvar_RegisterVariable(&r_depthfirst);
4294         Cvar_RegisterVariable(&r_useinfinitefarclip);
4295         Cvar_RegisterVariable(&r_farclip_base);
4296         Cvar_RegisterVariable(&r_farclip_world);
4297         Cvar_RegisterVariable(&r_nearclip);
4298         Cvar_RegisterVariable(&r_deformvertexes);
4299         Cvar_RegisterVariable(&r_transparent);
4300         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4301         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4302         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4303         Cvar_RegisterVariable(&r_showoverdraw);
4304         Cvar_RegisterVariable(&r_showbboxes);
4305         Cvar_RegisterVariable(&r_showsurfaces);
4306         Cvar_RegisterVariable(&r_showtris);
4307         Cvar_RegisterVariable(&r_shownormals);
4308         Cvar_RegisterVariable(&r_showlighting);
4309         Cvar_RegisterVariable(&r_showshadowvolumes);
4310         Cvar_RegisterVariable(&r_showcollisionbrushes);
4311         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4312         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4313         Cvar_RegisterVariable(&r_showdisabledepthtest);
4314         Cvar_RegisterVariable(&r_drawportals);
4315         Cvar_RegisterVariable(&r_drawentities);
4316         Cvar_RegisterVariable(&r_draw2d);
4317         Cvar_RegisterVariable(&r_drawworld);
4318         Cvar_RegisterVariable(&r_cullentities_trace);
4319         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4320         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4321         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4322         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4323         Cvar_RegisterVariable(&r_sortentities);
4324         Cvar_RegisterVariable(&r_drawviewmodel);
4325         Cvar_RegisterVariable(&r_drawexteriormodel);
4326         Cvar_RegisterVariable(&r_speeds);
4327         Cvar_RegisterVariable(&r_fullbrights);
4328         Cvar_RegisterVariable(&r_wateralpha);
4329         Cvar_RegisterVariable(&r_dynamic);
4330         Cvar_RegisterVariable(&r_fakelight);
4331         Cvar_RegisterVariable(&r_fakelight_intensity);
4332         Cvar_RegisterVariable(&r_fullbright);
4333         Cvar_RegisterVariable(&r_shadows);
4334         Cvar_RegisterVariable(&r_shadows_darken);
4335         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4336         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4337         Cvar_RegisterVariable(&r_shadows_throwdistance);
4338         Cvar_RegisterVariable(&r_shadows_throwdirection);
4339         Cvar_RegisterVariable(&r_shadows_focus);
4340         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4341         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4342         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4343         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4344         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4345         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4346         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4347         Cvar_RegisterVariable(&r_fog_exp2);
4348         Cvar_RegisterVariable(&r_fog_clear);
4349         Cvar_RegisterVariable(&r_drawfog);
4350         Cvar_RegisterVariable(&r_transparentdepthmasking);
4351         Cvar_RegisterVariable(&r_transparent_sortmindist);
4352         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4353         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4354         Cvar_RegisterVariable(&r_texture_dds_load);
4355         Cvar_RegisterVariable(&r_texture_dds_save);
4356         Cvar_RegisterVariable(&r_textureunits);
4357         Cvar_RegisterVariable(&gl_combine);
4358         Cvar_RegisterVariable(&r_usedepthtextures);
4359         Cvar_RegisterVariable(&r_viewfbo);
4360         Cvar_RegisterVariable(&r_viewscale);
4361         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4362         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4363         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4364         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4365         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4366         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4367         Cvar_RegisterVariable(&r_glsl);
4368         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4369         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4370         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4371         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4372         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4373         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4374         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4375         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4376         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4377         Cvar_RegisterVariable(&r_glsl_postprocess);
4378         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4379         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4380         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4381         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4382         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4383         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4384         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4385         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4386         Cvar_RegisterVariable(&r_celshading);
4387         Cvar_RegisterVariable(&r_celoutlines);
4388
4389         Cvar_RegisterVariable(&r_water);
4390         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4391         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4392         Cvar_RegisterVariable(&r_water_clippingplanebias);
4393         Cvar_RegisterVariable(&r_water_refractdistort);
4394         Cvar_RegisterVariable(&r_water_reflectdistort);
4395         Cvar_RegisterVariable(&r_water_scissormode);
4396         Cvar_RegisterVariable(&r_water_lowquality);
4397         Cvar_RegisterVariable(&r_water_hideplayer);
4398         Cvar_RegisterVariable(&r_water_fbo);
4399
4400         Cvar_RegisterVariable(&r_lerpsprites);
4401         Cvar_RegisterVariable(&r_lerpmodels);
4402         Cvar_RegisterVariable(&r_lerplightstyles);
4403         Cvar_RegisterVariable(&r_waterscroll);
4404         Cvar_RegisterVariable(&r_bloom);
4405         Cvar_RegisterVariable(&r_bloom_colorscale);
4406         Cvar_RegisterVariable(&r_bloom_brighten);
4407         Cvar_RegisterVariable(&r_bloom_blur);
4408         Cvar_RegisterVariable(&r_bloom_resolution);
4409         Cvar_RegisterVariable(&r_bloom_colorexponent);
4410         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4411         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4412         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4413         Cvar_RegisterVariable(&r_hdr_glowintensity);
4414         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4415         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4416         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4417         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4418         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4419         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4420         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4421         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4422         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4423         Cvar_RegisterVariable(&developer_texturelogging);
4424         Cvar_RegisterVariable(&gl_lightmaps);
4425         Cvar_RegisterVariable(&r_test);
4426         Cvar_RegisterVariable(&r_batch_multidraw);
4427         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4428         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4429         Cvar_RegisterVariable(&r_glsl_skeletal);
4430         Cvar_RegisterVariable(&r_glsl_saturation);
4431         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4432         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4433         Cvar_RegisterVariable(&r_framedatasize);
4434         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4435                 Cvar_RegisterVariable(&r_buffermegs[i]);
4436         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4437         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4438                 Cvar_SetValue("r_fullbrights", 0);
4439 #ifdef DP_MOBILETOUCH
4440         // GLES devices have terrible depth precision in general, so...
4441         Cvar_SetValueQuick(&r_nearclip, 4);
4442         Cvar_SetValueQuick(&r_farclip_base, 4096);
4443         Cvar_SetValueQuick(&r_farclip_world, 0);
4444         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4445 #endif
4446         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4447 }
4448
4449 void Render_Init(void)
4450 {
4451         gl_backend_init();
4452         R_Textures_Init();
4453         GL_Main_Init();
4454         Font_Init();
4455         GL_Draw_Init();
4456         R_Shadow_Init();
4457         R_Sky_Init();
4458         GL_Surf_Init();
4459         Sbar_Init();
4460         R_Particles_Init();
4461         R_Explosion_Init();
4462         R_LightningBeams_Init();
4463         Mod_RenderInit();
4464 }
4465
4466 /*
4467 ===============
4468 GL_Init
4469 ===============
4470 */
4471 #ifndef USE_GLES2
4472 extern char *ENGINE_EXTENSIONS;
4473 void GL_Init (void)
4474 {
4475         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4476         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4477         gl_version = (const char *)qglGetString(GL_VERSION);
4478         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4479
4480         if (!gl_extensions)
4481                 gl_extensions = "";
4482         if (!gl_platformextensions)
4483                 gl_platformextensions = "";
4484
4485         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4486         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4487         Con_Printf("GL_VERSION: %s\n", gl_version);
4488         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4489         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4490
4491         VID_CheckExtensions();
4492
4493         // LordHavoc: report supported extensions
4494 #ifdef CONFIG_MENU
4495         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4496 #else
4497         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4498 #endif
4499
4500         // clear to black (loading plaque will be seen over this)
4501         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4502 }
4503 #endif
4504
4505 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4506 {
4507         int i;
4508         mplane_t *p;
4509         if (r_trippy.integer)
4510                 return false;
4511         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4512         {
4513                 p = r_refdef.view.frustum + i;
4514                 switch(p->signbits)
4515                 {
4516                 default:
4517                 case 0:
4518                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4519                                 return true;
4520                         break;
4521                 case 1:
4522                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4523                                 return true;
4524                         break;
4525                 case 2:
4526                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4527                                 return true;
4528                         break;
4529                 case 3:
4530                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4531                                 return true;
4532                         break;
4533                 case 4:
4534                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4535                                 return true;
4536                         break;
4537                 case 5:
4538                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4539                                 return true;
4540                         break;
4541                 case 6:
4542                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4543                                 return true;
4544                         break;
4545                 case 7:
4546                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4547                                 return true;
4548                         break;
4549                 }
4550         }
4551         return false;
4552 }
4553
4554 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4555 {
4556         int i;
4557         const mplane_t *p;
4558         if (r_trippy.integer)
4559                 return false;
4560         for (i = 0;i < numplanes;i++)
4561         {
4562                 p = planes + i;
4563                 switch(p->signbits)
4564                 {
4565                 default:
4566                 case 0:
4567                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4568                                 return true;
4569                         break;
4570                 case 1:
4571                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4572                                 return true;
4573                         break;
4574                 case 2:
4575                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4576                                 return true;
4577                         break;
4578                 case 3:
4579                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4580                                 return true;
4581                         break;
4582                 case 4:
4583                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4584                                 return true;
4585                         break;
4586                 case 5:
4587                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4588                                 return true;
4589                         break;
4590                 case 6:
4591                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4592                                 return true;
4593                         break;
4594                 case 7:
4595                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4596                                 return true;
4597                         break;
4598                 }
4599         }
4600         return false;
4601 }
4602
4603 //==================================================================================
4604
4605 // LordHavoc: this stores temporary data used within the same frame
4606
4607 typedef struct r_framedata_mem_s
4608 {
4609         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4610         size_t size; // how much usable space
4611         size_t current; // how much space in use
4612         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4613         size_t wantedsize; // how much space was allocated
4614         unsigned char *data; // start of real data (16byte aligned)
4615 }
4616 r_framedata_mem_t;
4617
4618 static r_framedata_mem_t *r_framedata_mem;
4619
4620 void R_FrameData_Reset(void)
4621 {
4622         while (r_framedata_mem)
4623         {
4624                 r_framedata_mem_t *next = r_framedata_mem->purge;
4625                 Mem_Free(r_framedata_mem);
4626                 r_framedata_mem = next;
4627         }
4628 }
4629
4630 static void R_FrameData_Resize(qboolean mustgrow)
4631 {
4632         size_t wantedsize;
4633         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4634         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4635         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4636         {
4637                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4638                 newmem->wantedsize = wantedsize;
4639                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4640                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4641                 newmem->current = 0;
4642                 newmem->mark = 0;
4643                 newmem->purge = r_framedata_mem;
4644                 r_framedata_mem = newmem;
4645         }
4646 }
4647
4648 void R_FrameData_NewFrame(void)
4649 {
4650         R_FrameData_Resize(false);
4651         if (!r_framedata_mem)
4652                 return;
4653         // if we ran out of space on the last frame, free the old memory now
4654         while (r_framedata_mem->purge)
4655         {
4656                 // repeatedly remove the second item in the list, leaving only head
4657                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4658                 Mem_Free(r_framedata_mem->purge);
4659                 r_framedata_mem->purge = next;
4660         }
4661         // reset the current mem pointer
4662         r_framedata_mem->current = 0;
4663         r_framedata_mem->mark = 0;
4664 }
4665
4666 void *R_FrameData_Alloc(size_t size)
4667 {
4668         void *data;
4669         float newvalue;
4670
4671         // align to 16 byte boundary - the data pointer is already aligned, so we
4672         // only need to ensure the size of every allocation is also aligned
4673         size = (size + 15) & ~15;
4674
4675         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4676         {
4677                 // emergency - we ran out of space, allocate more memory
4678                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4679                 // this might not be a growing it, but we'll allocate another buffer every time
4680                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4681                 R_FrameData_Resize(true);
4682         }
4683
4684         data = r_framedata_mem->data + r_framedata_mem->current;
4685         r_framedata_mem->current += size;
4686
4687         // count the usage for stats
4688         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4689         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4690
4691         return (void *)data;
4692 }
4693
4694 void *R_FrameData_Store(size_t size, void *data)
4695 {
4696         void *d = R_FrameData_Alloc(size);
4697         if (d && data)
4698                 memcpy(d, data, size);
4699         return d;
4700 }
4701
4702 void R_FrameData_SetMark(void)
4703 {
4704         if (!r_framedata_mem)
4705                 return;
4706         r_framedata_mem->mark = r_framedata_mem->current;
4707 }
4708
4709 void R_FrameData_ReturnToMark(void)
4710 {
4711         if (!r_framedata_mem)
4712                 return;
4713         r_framedata_mem->current = r_framedata_mem->mark;
4714 }
4715
4716 //==================================================================================
4717
4718 // avoid reusing the same buffer objects on consecutive frames
4719 #define R_BUFFERDATA_CYCLE 3
4720
4721 typedef struct r_bufferdata_buffer_s
4722 {
4723         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4724         size_t size; // how much usable space
4725         size_t current; // how much space in use
4726         r_meshbuffer_t *buffer; // the buffer itself
4727 }
4728 r_bufferdata_buffer_t;
4729
4730 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4731 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4732
4733 /// frees all dynamic buffers
4734 void R_BufferData_Reset(void)
4735 {
4736         int cycle, type;
4737         r_bufferdata_buffer_t **p, *mem;
4738         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4739         {
4740                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4741                 {
4742                         // free all buffers
4743                         p = &r_bufferdata_buffer[cycle][type];
4744                         while (*p)
4745                         {
4746                                 mem = *p;
4747                                 *p = (*p)->purge;
4748                                 if (mem->buffer)
4749                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4750                                 Mem_Free(mem);
4751                         }
4752                 }
4753         }
4754 }
4755
4756 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4757 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4758 {
4759         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4760         size_t size;
4761         float newvalue = r_buffermegs[type].value;
4762
4763         // increase the cvar if we have to (but only if we already have a mem)
4764         if (mustgrow && mem)
4765                 newvalue *= 2.0f;
4766         newvalue = bound(0.25f, newvalue, 256.0f);
4767         while (newvalue * 1024*1024 < minsize)
4768                 newvalue *= 2.0f;
4769
4770         // clamp the cvar to valid range
4771         newvalue = bound(0.25f, newvalue, 256.0f);
4772         if (r_buffermegs[type].value != newvalue)
4773                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4774
4775         // calculate size in bytes
4776         size = (size_t)(newvalue * 1024*1024);
4777         size = bound(131072, size, 256*1024*1024);
4778
4779         // allocate a new buffer if the size is different (purge old one later)
4780         // or if we were told we must grow the buffer
4781         if (!mem || mem->size != size || mustgrow)
4782         {
4783                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4784                 mem->size = size;
4785                 mem->current = 0;
4786                 if (type == R_BUFFERDATA_VERTEX)
4787                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4788                 else if (type == R_BUFFERDATA_INDEX16)
4789                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4790                 else if (type == R_BUFFERDATA_INDEX32)
4791                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4792                 else if (type == R_BUFFERDATA_UNIFORM)
4793                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4794                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4795                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4796         }
4797 }
4798
4799 void R_BufferData_NewFrame(void)
4800 {
4801         int type;
4802         r_bufferdata_buffer_t **p, *mem;
4803         // cycle to the next frame's buffers
4804         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4805         // if we ran out of space on the last time we used these buffers, free the old memory now
4806         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4807         {
4808                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4809                 {
4810                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4811                         // free all but the head buffer, this is how we recycle obsolete
4812                         // buffers after they are no longer in use
4813                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4814                         while (*p)
4815                         {
4816                                 mem = *p;
4817                                 *p = (*p)->purge;
4818                                 if (mem->buffer)
4819                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4820                                 Mem_Free(mem);
4821                         }
4822                         // reset the current offset
4823                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4824                 }
4825         }
4826 }
4827
4828 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4829 {
4830         r_bufferdata_buffer_t *mem;
4831         int offset = 0;
4832         int padsize;
4833
4834         *returnbufferoffset = 0;
4835
4836         // align size to a byte boundary appropriate for the buffer type, this
4837         // makes all allocations have aligned start offsets
4838         if (type == R_BUFFERDATA_UNIFORM)
4839                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4840         else
4841                 padsize = (datasize + 15) & ~15;
4842
4843         // if we ran out of space in this buffer we must allocate a new one
4844         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4845                 R_BufferData_Resize(type, true, padsize);
4846
4847         // if the resize did not give us enough memory, fail
4848         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)
4849                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4850
4851         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4852         offset = (int)mem->current;
4853         mem->current += padsize;
4854
4855         // upload the data to the buffer at the chosen offset
4856         if (offset == 0)
4857                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4858         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4859
4860         // count the usage for stats
4861         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4862         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4863
4864         // return the buffer offset
4865         *returnbufferoffset = offset;
4866
4867         return mem->buffer;
4868 }
4869
4870 //==================================================================================
4871
4872 // LordHavoc: animcache originally written by Echon, rewritten since then
4873
4874 /**
4875  * Animation cache prevents re-generating mesh data for an animated model
4876  * multiple times in one frame for lighting, shadowing, reflections, etc.
4877  */
4878
4879 void R_AnimCache_Free(void)
4880 {
4881 }
4882
4883 void R_AnimCache_ClearCache(void)
4884 {
4885         int i;
4886         entity_render_t *ent;
4887
4888         for (i = 0;i < r_refdef.scene.numentities;i++)
4889         {
4890                 ent = r_refdef.scene.entities[i];
4891                 ent->animcache_vertex3f = NULL;
4892                 ent->animcache_vertex3f_vertexbuffer = NULL;
4893                 ent->animcache_vertex3f_bufferoffset = 0;
4894                 ent->animcache_normal3f = NULL;
4895                 ent->animcache_normal3f_vertexbuffer = NULL;
4896                 ent->animcache_normal3f_bufferoffset = 0;
4897                 ent->animcache_svector3f = NULL;
4898                 ent->animcache_svector3f_vertexbuffer = NULL;
4899                 ent->animcache_svector3f_bufferoffset = 0;
4900                 ent->animcache_tvector3f = NULL;
4901                 ent->animcache_tvector3f_vertexbuffer = NULL;
4902                 ent->animcache_tvector3f_bufferoffset = 0;
4903                 ent->animcache_vertexmesh = NULL;
4904                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4905                 ent->animcache_vertexmesh_bufferoffset = 0;
4906                 ent->animcache_skeletaltransform3x4 = NULL;
4907                 ent->animcache_skeletaltransform3x4buffer = NULL;
4908                 ent->animcache_skeletaltransform3x4offset = 0;
4909                 ent->animcache_skeletaltransform3x4size = 0;
4910         }
4911 }
4912
4913 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4914 {
4915         int i;
4916
4917         // check if we need the meshbuffers
4918         if (!vid.useinterleavedarrays)
4919                 return;
4920
4921         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4922                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4923         // TODO: upload vertexbuffer?
4924         if (ent->animcache_vertexmesh)
4925         {
4926                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4927                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4928                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4929                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4930                 for (i = 0;i < numvertices;i++)
4931                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4932                 if (ent->animcache_svector3f)
4933                         for (i = 0;i < numvertices;i++)
4934                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4935                 if (ent->animcache_tvector3f)
4936                         for (i = 0;i < numvertices;i++)
4937                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4938                 if (ent->animcache_normal3f)
4939                         for (i = 0;i < numvertices;i++)
4940                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4941         }
4942 }
4943
4944 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4945 {
4946         dp_model_t *model = ent->model;
4947         int numvertices;
4948
4949         // see if this ent is worth caching
4950         if (!model || !model->Draw || !model->AnimateVertices)
4951                 return false;
4952         // nothing to cache if it contains no animations and has no skeleton
4953         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4954                 return false;
4955         // see if it is already cached for gpuskeletal
4956         if (ent->animcache_skeletaltransform3x4)
4957                 return false;
4958         // see if it is already cached as a mesh
4959         if (ent->animcache_vertex3f)
4960         {
4961                 // check if we need to add normals or tangents
4962                 if (ent->animcache_normal3f)
4963                         wantnormals = false;
4964                 if (ent->animcache_svector3f)
4965                         wanttangents = false;
4966                 if (!wantnormals && !wanttangents)
4967                         return false;
4968         }
4969
4970         // check which kind of cache we need to generate
4971         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4972         {
4973                 // cache the skeleton so the vertex shader can use it
4974                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4975                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4976                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4977                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4978                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4979                 // note: this can fail if the buffer is at the grow limit
4980                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4981                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4982         }
4983         else if (ent->animcache_vertex3f)
4984         {
4985                 // mesh was already cached but we may need to add normals/tangents
4986                 // (this only happens with multiple views, reflections, cameras, etc)
4987                 if (wantnormals || wanttangents)
4988                 {
4989                         numvertices = model->surfmesh.num_vertices;
4990                         if (wantnormals)
4991                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4992                         if (wanttangents)
4993                         {
4994                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4995                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4996                         }
4997                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4998                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4999                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5000                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5001                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5002                 }
5003         }
5004         else
5005         {
5006                 // generate mesh cache
5007                 numvertices = model->surfmesh.num_vertices;
5008                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5009                 if (wantnormals)
5010                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5011                 if (wanttangents)
5012                 {
5013                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5014                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5015                 }
5016                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5017                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5018                 if (wantnormals || wanttangents)
5019                 {
5020                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5021                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5022                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5023                 }
5024                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5025                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5026                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5027         }
5028         return true;
5029 }
5030
5031 void R_AnimCache_CacheVisibleEntities(void)
5032 {
5033         int i;
5034         qboolean wantnormals = true;
5035         qboolean wanttangents = !r_showsurfaces.integer;
5036
5037         switch(vid.renderpath)
5038         {
5039         case RENDERPATH_GL20:
5040         case RENDERPATH_D3D9:
5041         case RENDERPATH_D3D10:
5042         case RENDERPATH_D3D11:
5043         case RENDERPATH_GLES2:
5044                 break;
5045         case RENDERPATH_GL11:
5046         case RENDERPATH_GL13:
5047         case RENDERPATH_GLES1:
5048                 wanttangents = false;
5049                 break;
5050         case RENDERPATH_SOFT:
5051                 break;
5052         }
5053
5054         if (r_shownormals.integer)
5055                 wanttangents = wantnormals = true;
5056
5057         // TODO: thread this
5058         // NOTE: R_PrepareRTLights() also caches entities
5059
5060         for (i = 0;i < r_refdef.scene.numentities;i++)
5061                 if (r_refdef.viewcache.entityvisible[i])
5062                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5063 }
5064
5065 //==================================================================================
5066
5067 extern cvar_t r_overheadsprites_pushback;
5068
5069 static void R_View_UpdateEntityLighting (void)
5070 {
5071         int i;
5072         entity_render_t *ent;
5073         vec3_t tempdiffusenormal, avg;
5074         vec_t f, fa, fd, fdd;
5075         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5076
5077         for (i = 0;i < r_refdef.scene.numentities;i++)
5078         {
5079                 ent = r_refdef.scene.entities[i];
5080
5081                 // skip unseen models
5082                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5083                         continue;
5084
5085                 // skip bsp models
5086                 if (ent->model && ent->model == cl.worldmodel)
5087                 {
5088                         // TODO: use modellight for r_ambient settings on world?
5089                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5090                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5091                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5092                         continue;
5093                 }
5094                 
5095                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5096                 {
5097                         // aleady updated by CSQC
5098                         // TODO: force modellight on BSP models in this case?
5099                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5100                 }
5101                 else
5102                 {
5103                         // fetch the lighting from the worldmodel data
5104                         VectorClear(ent->modellight_ambient);
5105                         VectorClear(ent->modellight_diffuse);
5106                         VectorClear(tempdiffusenormal);
5107                         if (ent->flags & RENDER_LIGHT)
5108                         {
5109                                 vec3_t org;
5110                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5111
5112                                 // complete lightning for lit sprites
5113                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5114                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5115                                 {
5116                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5117                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5118                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5119                                 }
5120                                 else
5121                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5122
5123                                 if(ent->flags & RENDER_EQUALIZE)
5124                                 {
5125                                         // first fix up ambient lighting...
5126                                         if(r_equalize_entities_minambient.value > 0)
5127                                         {
5128                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5129                                                 if(fd > 0)
5130                                                 {
5131                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5132                                                         if(fa < r_equalize_entities_minambient.value * fd)
5133                                                         {
5134                                                                 // solve:
5135                                                                 //   fa'/fd' = minambient
5136                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5137                                                                 //   ...
5138                                                                 //   fa' = fd' * minambient
5139                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5140                                                                 //   ...
5141                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5142                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5143                                                                 //   ...
5144                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5145                                                                 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
5146                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5147                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5148                                                         }
5149                                                 }
5150                                         }
5151
5152                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5153                                         {
5154                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5155                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5156                                                 f = fa + 0.25 * fd;
5157                                                 if(f > 0)
5158                                                 {
5159                                                         // adjust brightness and saturation to target
5160                                                         avg[0] = avg[1] = avg[2] = fa / f;
5161                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5162                                                         avg[0] = avg[1] = avg[2] = fd / f;
5163                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5164                                                 }
5165                                         }
5166                                 }
5167                         }
5168                         else // highly rare
5169                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5170                 }
5171
5172                 // move the light direction into modelspace coordinates for lighting code
5173                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5174                 if(VectorLength2(ent->modellight_lightdir) == 0)
5175                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5176                 VectorNormalize(ent->modellight_lightdir);
5177         }
5178 }
5179
5180 #define MAX_LINEOFSIGHTTRACES 64
5181
5182 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5183 {
5184         int i;
5185         vec3_t boxmins, boxmaxs;
5186         vec3_t start;
5187         vec3_t end;
5188         dp_model_t *model = r_refdef.scene.worldmodel;
5189
5190         if (!model || !model->brush.TraceLineOfSight)
5191                 return true;
5192
5193         // expand the box a little
5194         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5195         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5196         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5197         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5198         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5199         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5200
5201         // return true if eye is inside enlarged box
5202         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5203                 return true;
5204
5205         // try center
5206         VectorCopy(eye, start);
5207         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5208         if (model->brush.TraceLineOfSight(model, start, end))
5209                 return true;
5210
5211         // try various random positions
5212         for (i = 0;i < numsamples;i++)
5213         {
5214                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5215                 if (model->brush.TraceLineOfSight(model, start, end))
5216                         return true;
5217         }
5218
5219         return false;
5220 }
5221
5222
5223 static void R_View_UpdateEntityVisible (void)
5224 {
5225         int i;
5226         int renderimask;
5227         int samples;
5228         entity_render_t *ent;
5229
5230         if (r_refdef.envmap || r_fb.water.hideplayer)
5231                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5232         else if (chase_active.integer || r_fb.water.renderingscene)
5233                 renderimask = RENDER_VIEWMODEL;
5234         else
5235                 renderimask = RENDER_EXTERIORMODEL;
5236         if (!r_drawviewmodel.integer)
5237                 renderimask |= RENDER_VIEWMODEL;
5238         if (!r_drawexteriormodel.integer)
5239                 renderimask |= RENDER_EXTERIORMODEL;
5240         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5241         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5242         {
5243                 // worldmodel can check visibility
5244                 for (i = 0;i < r_refdef.scene.numentities;i++)
5245                 {
5246                         ent = r_refdef.scene.entities[i];
5247                         if (!(ent->flags & renderimask))
5248                         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)))
5249                         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))
5250                                 r_refdef.viewcache.entityvisible[i] = true;
5251                 }
5252         }
5253         else
5254         {
5255                 // no worldmodel or it can't check visibility
5256                 for (i = 0;i < r_refdef.scene.numentities;i++)
5257                 {
5258                         ent = r_refdef.scene.entities[i];
5259                         if (!(ent->flags & renderimask))
5260                         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)))
5261                                 r_refdef.viewcache.entityvisible[i] = true;
5262                 }
5263         }
5264         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5265                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5266         {
5267                 for (i = 0;i < r_refdef.scene.numentities;i++)
5268                 {
5269                         if (!r_refdef.viewcache.entityvisible[i])
5270                                 continue;
5271                         ent = r_refdef.scene.entities[i];
5272                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5273                         {
5274                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5275                                 if (samples < 0)
5276                                         continue; // temp entities do pvs only
5277                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5278                                         ent->last_trace_visibility = realtime;
5279                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5280                                         r_refdef.viewcache.entityvisible[i] = 0;
5281                         }
5282                 }
5283         }
5284 }
5285
5286 /// only used if skyrendermasked, and normally returns false
5287 static int R_DrawBrushModelsSky (void)
5288 {
5289         int i, sky;
5290         entity_render_t *ent;
5291
5292         sky = false;
5293         for (i = 0;i < r_refdef.scene.numentities;i++)
5294         {
5295                 if (!r_refdef.viewcache.entityvisible[i])
5296                         continue;
5297                 ent = r_refdef.scene.entities[i];
5298                 if (!ent->model || !ent->model->DrawSky)
5299                         continue;
5300                 ent->model->DrawSky(ent);
5301                 sky = true;
5302         }
5303         return sky;
5304 }
5305
5306 static void R_DrawNoModel(entity_render_t *ent);
5307 static void R_DrawModels(void)
5308 {
5309         int i;
5310         entity_render_t *ent;
5311
5312         for (i = 0;i < r_refdef.scene.numentities;i++)
5313         {
5314                 if (!r_refdef.viewcache.entityvisible[i])
5315                         continue;
5316                 ent = r_refdef.scene.entities[i];
5317                 r_refdef.stats[r_stat_entities]++;
5318                 /*
5319                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5320                 {
5321                         vec3_t f, l, u, o;
5322                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5323                         Con_Printf("R_DrawModels\n");
5324                         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]);
5325                         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);
5326                         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);
5327                 }
5328                 */
5329                 if (ent->model && ent->model->Draw != NULL)
5330                         ent->model->Draw(ent);
5331                 else
5332                         R_DrawNoModel(ent);
5333         }
5334 }
5335
5336 static void R_DrawModelsDepth(void)
5337 {
5338         int i;
5339         entity_render_t *ent;
5340
5341         for (i = 0;i < r_refdef.scene.numentities;i++)
5342         {
5343                 if (!r_refdef.viewcache.entityvisible[i])
5344                         continue;
5345                 ent = r_refdef.scene.entities[i];
5346                 if (ent->model && ent->model->DrawDepth != NULL)
5347                         ent->model->DrawDepth(ent);
5348         }
5349 }
5350
5351 static void R_DrawModelsDebug(void)
5352 {
5353         int i;
5354         entity_render_t *ent;
5355
5356         for (i = 0;i < r_refdef.scene.numentities;i++)
5357         {
5358                 if (!r_refdef.viewcache.entityvisible[i])
5359                         continue;
5360                 ent = r_refdef.scene.entities[i];
5361                 if (ent->model && ent->model->DrawDebug != NULL)
5362                         ent->model->DrawDebug(ent);
5363         }
5364 }
5365
5366 static void R_DrawModelsAddWaterPlanes(void)
5367 {
5368         int i;
5369         entity_render_t *ent;
5370
5371         for (i = 0;i < r_refdef.scene.numentities;i++)
5372         {
5373                 if (!r_refdef.viewcache.entityvisible[i])
5374                         continue;
5375                 ent = r_refdef.scene.entities[i];
5376                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5377                         ent->model->DrawAddWaterPlanes(ent);
5378         }
5379 }
5380
5381 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}};
5382
5383 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5384 {
5385         if (r_hdr_irisadaptation.integer)
5386         {
5387                 vec3_t p;
5388                 vec3_t ambient;
5389                 vec3_t diffuse;
5390                 vec3_t diffusenormal;
5391                 vec3_t forward;
5392                 vec_t brightness = 0.0f;
5393                 vec_t goal;
5394                 vec_t current;
5395                 vec_t d;
5396                 int c;
5397                 VectorCopy(r_refdef.view.forward, forward);
5398                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5399                 {
5400                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5401                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5402                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5403                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5404                         d = DotProduct(forward, diffusenormal);
5405                         brightness += VectorLength(ambient);
5406                         if (d > 0)
5407                                 brightness += d * VectorLength(diffuse);
5408                 }
5409                 brightness *= 1.0f / c;
5410                 brightness += 0.00001f; // make sure it's never zero
5411                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5412                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5413                 current = r_hdr_irisadaptation_value.value;
5414                 if (current < goal)
5415                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5416                 else if (current > goal)
5417                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5418                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5419                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5420         }
5421         else if (r_hdr_irisadaptation_value.value != 1.0f)
5422                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5423 }
5424
5425 static void R_View_SetFrustum(const int *scissor)
5426 {
5427         int i;
5428         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5429         vec3_t forward, left, up, origin, v;
5430
5431         if(scissor)
5432         {
5433                 // flipped x coordinates (because x points left here)
5434                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5435                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5436
5437                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5438                 switch(vid.renderpath)
5439                 {
5440                         case RENDERPATH_D3D9:
5441                         case RENDERPATH_D3D10:
5442                         case RENDERPATH_D3D11:
5443                                 // non-flipped y coordinates
5444                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5445                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5446                                 break;
5447                         case RENDERPATH_SOFT:
5448                         case RENDERPATH_GL11:
5449                         case RENDERPATH_GL13:
5450                         case RENDERPATH_GL20:
5451                         case RENDERPATH_GLES1:
5452                         case RENDERPATH_GLES2:
5453                                 // non-flipped y coordinates
5454                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5455                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5456                                 break;
5457                 }
5458         }
5459
5460         // we can't trust r_refdef.view.forward and friends in reflected scenes
5461         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5462
5463 #if 0
5464         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5465         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5466         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5467         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5468         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5469         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5470         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5471         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5472         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5473         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5474         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5475         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5476 #endif
5477
5478 #if 0
5479         zNear = r_refdef.nearclip;
5480         nudge = 1.0 - 1.0 / (1<<23);
5481         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5482         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5483         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5484         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5485         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5486         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5487         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5488         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5489 #endif
5490
5491
5492
5493 #if 0
5494         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5495         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5496         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5497         r_refdef.view.frustum[0].dist = m[15] - m[12];
5498
5499         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5500         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5501         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5502         r_refdef.view.frustum[1].dist = m[15] + m[12];
5503
5504         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5505         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5506         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5507         r_refdef.view.frustum[2].dist = m[15] - m[13];
5508
5509         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5510         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5511         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5512         r_refdef.view.frustum[3].dist = m[15] + m[13];
5513
5514         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5515         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5516         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5517         r_refdef.view.frustum[4].dist = m[15] - m[14];
5518
5519         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5520         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5521         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5522         r_refdef.view.frustum[5].dist = m[15] + m[14];
5523 #endif
5524
5525         if (r_refdef.view.useperspective)
5526         {
5527                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5528                 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]);
5529                 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]);
5530                 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]);
5531                 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]);
5532
5533                 // then the normals from the corners relative to origin
5534                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5535                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5536                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5537                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5538
5539                 // in a NORMAL view, forward cross left == up
5540                 // in a REFLECTED view, forward cross left == down
5541                 // so our cross products above need to be adjusted for a left handed coordinate system
5542                 CrossProduct(forward, left, v);
5543                 if(DotProduct(v, up) < 0)
5544                 {
5545                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5546                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5547                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5548                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5549                 }
5550
5551                 // Leaving those out was a mistake, those were in the old code, and they
5552                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5553                 // I couldn't reproduce it after adding those normalizations. --blub
5554                 VectorNormalize(r_refdef.view.frustum[0].normal);
5555                 VectorNormalize(r_refdef.view.frustum[1].normal);
5556                 VectorNormalize(r_refdef.view.frustum[2].normal);
5557                 VectorNormalize(r_refdef.view.frustum[3].normal);
5558
5559                 // make the corners absolute
5560                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5561                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5562                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5563                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5564
5565                 // one more normal
5566                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5567
5568                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5569                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5570                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5571                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5572                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5573         }
5574         else
5575         {
5576                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5577                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5578                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5579                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5580                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5581                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5582                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5583                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5584                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5585                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5586         }
5587         r_refdef.view.numfrustumplanes = 5;
5588
5589         if (r_refdef.view.useclipplane)
5590         {
5591                 r_refdef.view.numfrustumplanes = 6;
5592                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5593         }
5594
5595         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5596                 PlaneClassify(r_refdef.view.frustum + i);
5597
5598         // LordHavoc: note to all quake engine coders, Quake had a special case
5599         // for 90 degrees which assumed a square view (wrong), so I removed it,
5600         // Quake2 has it disabled as well.
5601
5602         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5603         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5604         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5605         //PlaneClassify(&frustum[0]);
5606
5607         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5608         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5609         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5610         //PlaneClassify(&frustum[1]);
5611
5612         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5613         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5614         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5615         //PlaneClassify(&frustum[2]);
5616
5617         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5618         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5619         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5620         //PlaneClassify(&frustum[3]);
5621
5622         // nearclip plane
5623         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5624         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5625         //PlaneClassify(&frustum[4]);
5626 }
5627
5628 static void R_View_UpdateWithScissor(const int *myscissor)
5629 {
5630         R_Main_ResizeViewCache();
5631         R_View_SetFrustum(myscissor);
5632         R_View_WorldVisibility(r_refdef.view.useclipplane);
5633         R_View_UpdateEntityVisible();
5634         R_View_UpdateEntityLighting();
5635 }
5636
5637 static void R_View_Update(void)
5638 {
5639         R_Main_ResizeViewCache();
5640         R_View_SetFrustum(NULL);
5641         R_View_WorldVisibility(r_refdef.view.useclipplane);
5642         R_View_UpdateEntityVisible();
5643         R_View_UpdateEntityLighting();
5644 }
5645
5646 float viewscalefpsadjusted = 1.0f;
5647
5648 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5649 {
5650         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5651         scale = bound(0.03125f, scale, 1.0f);
5652         *outwidth = (int)ceil(width * scale);
5653         *outheight = (int)ceil(height * scale);
5654 }
5655
5656 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5657 {
5658         const float *customclipplane = NULL;
5659         float plane[4];
5660         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5661         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5662         {
5663                 // LordHavoc: couldn't figure out how to make this approach the
5664                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5665                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5666                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5667                         dist = r_refdef.view.clipplane.dist;
5668                 plane[0] = r_refdef.view.clipplane.normal[0];
5669                 plane[1] = r_refdef.view.clipplane.normal[1];
5670                 plane[2] = r_refdef.view.clipplane.normal[2];
5671                 plane[3] = -dist;
5672                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5673         }
5674
5675         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5676         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5677
5678         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5679         if (!r_refdef.view.useperspective)
5680                 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);
5681         else if (vid.stencil && r_useinfinitefarclip.integer)
5682                 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);
5683         else
5684                 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);
5685         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5686         R_SetViewport(&r_refdef.view.viewport);
5687         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5688         {
5689                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5690                 float screenplane[4];
5691                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5692                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5693                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5694                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5695                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5696         }
5697 }
5698
5699 void R_EntityMatrix(const matrix4x4_t *matrix)
5700 {
5701         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5702         {
5703                 gl_modelmatrixchanged = false;
5704                 gl_modelmatrix = *matrix;
5705                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5706                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5707                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5708                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5709                 CHECKGLERROR
5710                 switch(vid.renderpath)
5711                 {
5712                 case RENDERPATH_D3D9:
5713 #ifdef SUPPORTD3D
5714                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5715                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5716 #endif
5717                         break;
5718                 case RENDERPATH_D3D10:
5719                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5720                         break;
5721                 case RENDERPATH_D3D11:
5722                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5723                         break;
5724                 case RENDERPATH_GL11:
5725                 case RENDERPATH_GL13:
5726                 case RENDERPATH_GLES1:
5727 #ifndef USE_GLES2
5728                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5729 #endif
5730                         break;
5731                 case RENDERPATH_SOFT:
5732                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5733                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5734                         break;
5735                 case RENDERPATH_GL20:
5736                 case RENDERPATH_GLES2:
5737                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5738                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5739                         break;
5740                 }
5741         }
5742 }
5743
5744 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5745 {
5746         r_viewport_t viewport;
5747
5748         CHECKGLERROR
5749
5750         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5751         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);
5752         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5753         R_SetViewport(&viewport);
5754         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5755         GL_Color(1, 1, 1, 1);
5756         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5757         GL_BlendFunc(GL_ONE, GL_ZERO);
5758         GL_ScissorTest(false);
5759         GL_DepthMask(false);
5760         GL_DepthRange(0, 1);
5761         GL_DepthTest(false);
5762         GL_DepthFunc(GL_LEQUAL);
5763         R_EntityMatrix(&identitymatrix);
5764         R_Mesh_ResetTextureState();
5765         GL_PolygonOffset(0, 0);
5766         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5767         switch(vid.renderpath)
5768         {
5769         case RENDERPATH_GL11:
5770         case RENDERPATH_GL13:
5771         case RENDERPATH_GL20:
5772         case RENDERPATH_GLES1:
5773         case RENDERPATH_GLES2:
5774                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5775                 break;
5776         case RENDERPATH_D3D9:
5777         case RENDERPATH_D3D10:
5778         case RENDERPATH_D3D11:
5779         case RENDERPATH_SOFT:
5780                 break;
5781         }
5782         GL_CullFace(GL_NONE);
5783
5784         CHECKGLERROR
5785 }
5786
5787 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5788 {
5789         DrawQ_Finish();
5790
5791         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5792 }
5793
5794 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5795 {
5796         DrawQ_Finish();
5797
5798         R_SetupView(true, fbo, depthtexture, colortexture);
5799         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5800         GL_Color(1, 1, 1, 1);
5801         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5802         GL_BlendFunc(GL_ONE, GL_ZERO);
5803         GL_ScissorTest(true);
5804         GL_DepthMask(true);
5805         GL_DepthRange(0, 1);
5806         GL_DepthTest(true);
5807         GL_DepthFunc(GL_LEQUAL);
5808         R_EntityMatrix(&identitymatrix);
5809         R_Mesh_ResetTextureState();
5810         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5811         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5812         switch(vid.renderpath)
5813         {
5814         case RENDERPATH_GL11:
5815         case RENDERPATH_GL13:
5816         case RENDERPATH_GL20:
5817         case RENDERPATH_GLES1:
5818         case RENDERPATH_GLES2:
5819                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5820                 break;
5821         case RENDERPATH_D3D9:
5822         case RENDERPATH_D3D10:
5823         case RENDERPATH_D3D11:
5824         case RENDERPATH_SOFT:
5825                 break;
5826         }
5827         GL_CullFace(r_refdef.view.cullface_back);
5828 }
5829
5830 /*
5831 ================
5832 R_RenderView_UpdateViewVectors
5833 ================
5834 */
5835 void R_RenderView_UpdateViewVectors(void)
5836 {
5837         // break apart the view matrix into vectors for various purposes
5838         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5839         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5840         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5841         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5842         // make an inverted copy of the view matrix for tracking sprites
5843         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5844 }
5845
5846 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5847 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5848
5849 static void R_Water_StartFrame(void)
5850 {
5851         int i;
5852         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5853         r_waterstate_waterplane_t *p;
5854         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;
5855
5856         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5857                 return;
5858
5859         switch(vid.renderpath)
5860         {
5861         case RENDERPATH_GL20:
5862         case RENDERPATH_D3D9:
5863         case RENDERPATH_D3D10:
5864         case RENDERPATH_D3D11:
5865         case RENDERPATH_SOFT:
5866         case RENDERPATH_GLES2:
5867                 break;
5868         case RENDERPATH_GL11:
5869         case RENDERPATH_GL13:
5870         case RENDERPATH_GLES1:
5871                 return;
5872         }
5873
5874         // set waterwidth and waterheight to the water resolution that will be
5875         // used (often less than the screen resolution for faster rendering)
5876         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5877
5878         // calculate desired texture sizes
5879         // can't use water if the card does not support the texture size
5880         if (!r_water.integer || r_showsurfaces.integer)
5881                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5882         else if (vid.support.arb_texture_non_power_of_two)
5883         {
5884                 texturewidth = waterwidth;
5885                 textureheight = waterheight;
5886                 camerawidth = waterwidth;
5887                 cameraheight = waterheight;
5888         }
5889         else
5890         {
5891                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5892                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5893                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5894                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5895         }
5896
5897         // allocate textures as needed
5898         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))
5899         {
5900                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5901                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5902                 {
5903                         if (p->texture_refraction)
5904                                 R_FreeTexture(p->texture_refraction);
5905                         p->texture_refraction = NULL;
5906                         if (p->fbo_refraction)
5907                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5908                         p->fbo_refraction = 0;
5909                         if (p->texture_reflection)
5910                                 R_FreeTexture(p->texture_reflection);
5911                         p->texture_reflection = NULL;
5912                         if (p->fbo_reflection)
5913                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5914                         p->fbo_reflection = 0;
5915                         if (p->texture_camera)
5916                                 R_FreeTexture(p->texture_camera);
5917                         p->texture_camera = NULL;
5918                         if (p->fbo_camera)
5919                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5920                         p->fbo_camera = 0;
5921                 }
5922                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5923                 r_fb.water.texturewidth = texturewidth;
5924                 r_fb.water.textureheight = textureheight;
5925                 r_fb.water.camerawidth = camerawidth;
5926                 r_fb.water.cameraheight = cameraheight;
5927         }
5928
5929         if (r_fb.water.texturewidth)
5930         {
5931                 int scaledwidth, scaledheight;
5932
5933                 r_fb.water.enabled = true;
5934
5935                 // water resolution is usually reduced
5936                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5937                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5938                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5939
5940                 // set up variables that will be used in shader setup
5941                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5942                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5943                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5944                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5945         }
5946
5947         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5948         r_fb.water.numwaterplanes = 0;
5949 }
5950
5951 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5952 {
5953         int planeindex, bestplaneindex, vertexindex;
5954         vec3_t mins, maxs, normal, center, v, n;
5955         vec_t planescore, bestplanescore;
5956         mplane_t plane;
5957         r_waterstate_waterplane_t *p;
5958         texture_t *t = R_GetCurrentTexture(surface->texture);
5959
5960         rsurface.texture = t;
5961         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5962         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5963         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5964                 return;
5965         // average the vertex normals, find the surface bounds (after deformvertexes)
5966         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5967         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5968         VectorCopy(n, normal);
5969         VectorCopy(v, mins);
5970         VectorCopy(v, maxs);
5971         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5972         {
5973                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5974                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5975                 VectorAdd(normal, n, normal);
5976                 mins[0] = min(mins[0], v[0]);
5977                 mins[1] = min(mins[1], v[1]);
5978                 mins[2] = min(mins[2], v[2]);
5979                 maxs[0] = max(maxs[0], v[0]);
5980                 maxs[1] = max(maxs[1], v[1]);
5981                 maxs[2] = max(maxs[2], v[2]);
5982         }
5983         VectorNormalize(normal);
5984         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5985
5986         VectorCopy(normal, plane.normal);
5987         VectorNormalize(plane.normal);
5988         plane.dist = DotProduct(center, plane.normal);
5989         PlaneClassify(&plane);
5990         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5991         {
5992                 // skip backfaces (except if nocullface is set)
5993 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5994 //                      return;
5995                 VectorNegate(plane.normal, plane.normal);
5996                 plane.dist *= -1;
5997                 PlaneClassify(&plane);
5998         }
5999
6000
6001         // find a matching plane if there is one
6002         bestplaneindex = -1;
6003         bestplanescore = 1048576.0f;
6004         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6005         {
6006                 if(p->camera_entity == t->camera_entity)
6007                 {
6008                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6009                         if (bestplaneindex < 0 || bestplanescore > planescore)
6010                         {
6011                                 bestplaneindex = planeindex;
6012                                 bestplanescore = planescore;
6013                         }
6014                 }
6015         }
6016         planeindex = bestplaneindex;
6017
6018         // if this surface does not fit any known plane rendered this frame, add one
6019         if (planeindex < 0 || bestplanescore > 0.001f)
6020         {
6021                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6022                 {
6023                         // store the new plane
6024                         planeindex = r_fb.water.numwaterplanes++;
6025                         p = r_fb.water.waterplanes + planeindex;
6026                         p->plane = plane;
6027                         // clear materialflags and pvs
6028                         p->materialflags = 0;
6029                         p->pvsvalid = false;
6030                         p->camera_entity = t->camera_entity;
6031                         VectorCopy(mins, p->mins);
6032                         VectorCopy(maxs, p->maxs);
6033                 }
6034                 else
6035                 {
6036                         // We're totally screwed.
6037                         return;
6038                 }
6039         }
6040         else
6041         {
6042                 // merge mins/maxs when we're adding this surface to the plane
6043                 p = r_fb.water.waterplanes + planeindex;
6044                 p->mins[0] = min(p->mins[0], mins[0]);
6045                 p->mins[1] = min(p->mins[1], mins[1]);
6046                 p->mins[2] = min(p->mins[2], mins[2]);
6047                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6048                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6049                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6050         }
6051         // merge this surface's materialflags into the waterplane
6052         p->materialflags |= t->currentmaterialflags;
6053         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6054         {
6055                 // merge this surface's PVS into the waterplane
6056                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6057                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6058                 {
6059                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6060                         p->pvsvalid = true;
6061                 }
6062         }
6063 }
6064
6065 extern cvar_t r_drawparticles;
6066 extern cvar_t r_drawdecals;
6067
6068 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6069 {
6070         int myscissor[4];
6071         r_refdef_view_t originalview;
6072         r_refdef_view_t myview;
6073         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;
6074         r_waterstate_waterplane_t *p;
6075         vec3_t visorigin;
6076         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;
6077         char vabuf[1024];
6078
6079         originalview = r_refdef.view;
6080
6081         // lowquality hack, temporarily shut down some cvars and restore afterwards
6082         qualityreduction = r_water_lowquality.integer;
6083         if (qualityreduction > 0)
6084         {
6085                 if (qualityreduction >= 1)
6086                 {
6087                         old_r_shadows = r_shadows.integer;
6088                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6089                         old_r_dlight = r_shadow_realtime_dlight.integer;
6090                         Cvar_SetValueQuick(&r_shadows, 0);
6091                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6092                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6093                 }
6094                 if (qualityreduction >= 2)
6095                 {
6096                         old_r_dynamic = r_dynamic.integer;
6097                         old_r_particles = r_drawparticles.integer;
6098                         old_r_decals = r_drawdecals.integer;
6099                         Cvar_SetValueQuick(&r_dynamic, 0);
6100                         Cvar_SetValueQuick(&r_drawparticles, 0);
6101                         Cvar_SetValueQuick(&r_drawdecals, 0);
6102                 }
6103         }
6104
6105         // make sure enough textures are allocated
6106         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6107         {
6108                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6109                         continue;
6110                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6111                 {
6112                         if (!p->texture_refraction)
6113                                 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);
6114                         if (!p->texture_refraction)
6115                                 goto error;
6116                         if (usewaterfbo)
6117                         {
6118                                 if (r_fb.water.depthtexture == NULL)
6119                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6120                                 if (p->fbo_refraction == 0)
6121                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6122                         }
6123                 }
6124                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6125                 {
6126                         if (!p->texture_camera)
6127                                 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);
6128                         if (!p->texture_camera)
6129                                 goto error;
6130                         if (usewaterfbo)
6131                         {
6132                                 if (r_fb.water.depthtexture == NULL)
6133                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6134                                 if (p->fbo_camera == 0)
6135                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6136                         }
6137                 }
6138
6139                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6140                 {
6141                         if (!p->texture_reflection)
6142                                 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);
6143                         if (!p->texture_reflection)
6144                                 goto error;
6145                         if (usewaterfbo)
6146                         {
6147                                 if (r_fb.water.depthtexture == NULL)
6148                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6149                                 if (p->fbo_reflection == 0)
6150                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6151                         }
6152                 }
6153         }
6154
6155         // render views
6156         r_refdef.view = originalview;
6157         r_refdef.view.showdebug = false;
6158         r_refdef.view.width = r_fb.water.waterwidth;
6159         r_refdef.view.height = r_fb.water.waterheight;
6160         r_refdef.view.useclipplane = true;
6161         myview = r_refdef.view;
6162         r_fb.water.renderingscene = true;
6163         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6164         {
6165                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6166                         continue;
6167                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6168                 {
6169                         r_refdef.view = myview;
6170                         if(r_water_scissormode.integer)
6171                         {
6172                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6173                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6174                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6175                         }
6176
6177                         // render reflected scene and copy into texture
6178                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6179                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6180                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6181                         r_refdef.view.clipplane = p->plane;
6182                         // reverse the cullface settings for this render
6183                         r_refdef.view.cullface_front = GL_FRONT;
6184                         r_refdef.view.cullface_back = GL_BACK;
6185                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6186                         {
6187                                 r_refdef.view.usecustompvs = true;
6188                                 if (p->pvsvalid)
6189                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6190                                 else
6191                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6192                         }
6193
6194                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6195                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6196                         R_ClearScreen(r_refdef.fogenabled);
6197                         if(r_water_scissormode.integer & 2)
6198                                 R_View_UpdateWithScissor(myscissor);
6199                         else
6200                                 R_View_Update();
6201                         R_AnimCache_CacheVisibleEntities();
6202                         if(r_water_scissormode.integer & 1)
6203                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6204                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6205
6206                         if (!p->fbo_reflection)
6207                                 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);
6208                         r_fb.water.hideplayer = false;
6209                 }
6210
6211                 // render the normal view scene and copy into texture
6212                 // (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)
6213                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6214                 {
6215                         r_refdef.view = myview;
6216                         if(r_water_scissormode.integer)
6217                         {
6218                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6219                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6220                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6221                         }
6222
6223                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6224
6225                         r_refdef.view.clipplane = p->plane;
6226                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6227                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6228
6229                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6230                         {
6231                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6232                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6233                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6234                                 R_RenderView_UpdateViewVectors();
6235                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6236                                 {
6237                                         r_refdef.view.usecustompvs = true;
6238                                         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);
6239                                 }
6240                         }
6241
6242                         PlaneClassify(&r_refdef.view.clipplane);
6243
6244                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6245                         R_ClearScreen(r_refdef.fogenabled);
6246                         if(r_water_scissormode.integer & 2)
6247                                 R_View_UpdateWithScissor(myscissor);
6248                         else
6249                                 R_View_Update();
6250                         R_AnimCache_CacheVisibleEntities();
6251                         if(r_water_scissormode.integer & 1)
6252                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6253                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6254
6255                         if (!p->fbo_refraction)
6256                                 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);
6257                         r_fb.water.hideplayer = false;
6258                 }
6259                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6260                 {
6261                         r_refdef.view = myview;
6262
6263                         r_refdef.view.clipplane = p->plane;
6264                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6265                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6266
6267                         r_refdef.view.width = r_fb.water.camerawidth;
6268                         r_refdef.view.height = r_fb.water.cameraheight;
6269                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6270                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6271                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6272                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6273
6274                         if(p->camera_entity)
6275                         {
6276                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6277                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6278                         }
6279
6280                         // note: all of the view is used for displaying... so
6281                         // there is no use in scissoring
6282
6283                         // reverse the cullface settings for this render
6284                         r_refdef.view.cullface_front = GL_FRONT;
6285                         r_refdef.view.cullface_back = GL_BACK;
6286                         // also reverse the view matrix
6287                         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
6288                         R_RenderView_UpdateViewVectors();
6289                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6290                         {
6291                                 r_refdef.view.usecustompvs = true;
6292                                 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);
6293                         }
6294                         
6295                         // camera needs no clipplane
6296                         r_refdef.view.useclipplane = false;
6297
6298                         PlaneClassify(&r_refdef.view.clipplane);
6299
6300                         r_fb.water.hideplayer = false;
6301
6302                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6303                         R_ClearScreen(r_refdef.fogenabled);
6304                         R_View_Update();
6305                         R_AnimCache_CacheVisibleEntities();
6306                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6307
6308                         if (!p->fbo_camera)
6309                                 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);
6310                         r_fb.water.hideplayer = false;
6311                 }
6312
6313         }
6314         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6315         r_fb.water.renderingscene = false;
6316         r_refdef.view = originalview;
6317         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6318         if (!r_fb.water.depthtexture)
6319                 R_ClearScreen(r_refdef.fogenabled);
6320         R_View_Update();
6321         R_AnimCache_CacheVisibleEntities();
6322         goto finish;
6323 error:
6324         r_refdef.view = originalview;
6325         r_fb.water.renderingscene = false;
6326         Cvar_SetValueQuick(&r_water, 0);
6327         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6328 finish:
6329         // lowquality hack, restore cvars
6330         if (qualityreduction > 0)
6331         {
6332                 if (qualityreduction >= 1)
6333                 {
6334                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6335                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6336                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6337                 }
6338                 if (qualityreduction >= 2)
6339                 {
6340                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6341                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6342                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6343                 }
6344         }
6345 }
6346
6347 static void R_Bloom_StartFrame(void)
6348 {
6349         int i;
6350         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6351         int viewwidth, viewheight;
6352         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6353         textype_t textype = TEXTYPE_COLORBUFFER;
6354
6355         switch (vid.renderpath)
6356         {
6357         case RENDERPATH_GL20:
6358                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6359                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6360                 {
6361                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6362                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6363                 }
6364                 break;
6365         case RENDERPATH_GL11:
6366         case RENDERPATH_GL13:
6367         case RENDERPATH_GLES1:
6368         case RENDERPATH_GLES2:
6369         case RENDERPATH_D3D9:
6370         case RENDERPATH_D3D10:
6371         case RENDERPATH_D3D11:
6372                 r_fb.usedepthtextures = false;
6373                 break;
6374         case RENDERPATH_SOFT:
6375                 r_fb.usedepthtextures = true;
6376                 break;
6377         }
6378
6379         if (r_viewscale_fpsscaling.integer)
6380         {
6381                 double actualframetime;
6382                 double targetframetime;
6383                 double adjust;
6384                 actualframetime = r_refdef.lastdrawscreentime;
6385                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6386                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6387                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6388                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6389                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6390                 viewscalefpsadjusted += adjust;
6391                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6392         }
6393         else
6394                 viewscalefpsadjusted = 1.0f;
6395
6396         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6397
6398         switch(vid.renderpath)
6399         {
6400         case RENDERPATH_GL20:
6401         case RENDERPATH_D3D9:
6402         case RENDERPATH_D3D10:
6403         case RENDERPATH_D3D11:
6404         case RENDERPATH_SOFT:
6405         case RENDERPATH_GLES2:
6406                 break;
6407         case RENDERPATH_GL11:
6408         case RENDERPATH_GL13:
6409         case RENDERPATH_GLES1:
6410                 return;
6411         }
6412
6413         // set bloomwidth and bloomheight to the bloom resolution that will be
6414         // used (often less than the screen resolution for faster rendering)
6415         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6416         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6417         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6418         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6419         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6420
6421         // calculate desired texture sizes
6422         if (vid.support.arb_texture_non_power_of_two)
6423         {
6424                 screentexturewidth = vid.width;
6425                 screentextureheight = vid.height;
6426                 bloomtexturewidth = r_fb.bloomwidth;
6427                 bloomtextureheight = r_fb.bloomheight;
6428         }
6429         else
6430         {
6431                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6432                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6433                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6434                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6435         }
6436
6437         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))
6438         {
6439                 Cvar_SetValueQuick(&r_bloom, 0);
6440                 Cvar_SetValueQuick(&r_motionblur, 0);
6441                 Cvar_SetValueQuick(&r_damageblur, 0);
6442         }
6443
6444         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6445          && !r_bloom.integer
6446          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6447          && !useviewfbo
6448          && r_viewscale.value == 1.0f
6449          && !r_viewscale_fpsscaling.integer)
6450                 screentexturewidth = screentextureheight = 0;
6451         if (!r_bloom.integer)
6452                 bloomtexturewidth = bloomtextureheight = 0;
6453
6454         // allocate textures as needed
6455         if (r_fb.screentexturewidth != screentexturewidth
6456          || r_fb.screentextureheight != screentextureheight
6457          || r_fb.bloomtexturewidth != bloomtexturewidth
6458          || r_fb.bloomtextureheight != bloomtextureheight
6459          || r_fb.textype != textype
6460          || useviewfbo != (r_fb.fbo != 0))
6461         {
6462                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6463                 {
6464                         if (r_fb.bloomtexture[i])
6465                                 R_FreeTexture(r_fb.bloomtexture[i]);
6466                         r_fb.bloomtexture[i] = NULL;
6467
6468                         if (r_fb.bloomfbo[i])
6469                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6470                         r_fb.bloomfbo[i] = 0;
6471                 }
6472
6473                 if (r_fb.fbo)
6474                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6475                 r_fb.fbo = 0;
6476
6477                 if (r_fb.colortexture)
6478                         R_FreeTexture(r_fb.colortexture);
6479                 r_fb.colortexture = NULL;
6480
6481                 if (r_fb.depthtexture)
6482                         R_FreeTexture(r_fb.depthtexture);
6483                 r_fb.depthtexture = NULL;
6484
6485                 if (r_fb.ghosttexture)
6486                         R_FreeTexture(r_fb.ghosttexture);
6487                 r_fb.ghosttexture = NULL;
6488
6489                 r_fb.screentexturewidth = screentexturewidth;
6490                 r_fb.screentextureheight = screentextureheight;
6491                 r_fb.bloomtexturewidth = bloomtexturewidth;
6492                 r_fb.bloomtextureheight = bloomtextureheight;
6493                 r_fb.textype = textype;
6494
6495                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6496                 {
6497                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6498                                 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);
6499                         r_fb.ghosttexture_valid = false;
6500                         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);
6501                         if (useviewfbo)
6502                         {
6503                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6504                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6505                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6506                         }
6507                 }
6508
6509                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6510                 {
6511                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6512                         {
6513                                 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);
6514                                 if (useviewfbo)
6515                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6516                         }
6517                 }
6518         }
6519
6520         // bloom texture is a different resolution
6521         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6522         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6523         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6524         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6525         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6526
6527         // set up a texcoord array for the full resolution screen image
6528         // (we have to keep this around to copy back during final render)
6529         r_fb.screentexcoord2f[0] = 0;
6530         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6531         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6532         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6533         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6534         r_fb.screentexcoord2f[5] = 0;
6535         r_fb.screentexcoord2f[6] = 0;
6536         r_fb.screentexcoord2f[7] = 0;
6537
6538         if(r_fb.fbo) 
6539         {
6540                 for (i = 1;i < 8;i += 2)
6541                 {
6542                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6543                 }
6544         }
6545
6546         // set up a texcoord array for the reduced resolution bloom image
6547         // (which will be additive blended over the screen image)
6548         r_fb.bloomtexcoord2f[0] = 0;
6549         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6550         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6551         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6552         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6553         r_fb.bloomtexcoord2f[5] = 0;
6554         r_fb.bloomtexcoord2f[6] = 0;
6555         r_fb.bloomtexcoord2f[7] = 0;
6556
6557         switch(vid.renderpath)
6558         {
6559         case RENDERPATH_GL11:
6560         case RENDERPATH_GL13:
6561         case RENDERPATH_GL20:
6562         case RENDERPATH_SOFT:
6563         case RENDERPATH_GLES1:
6564         case RENDERPATH_GLES2:
6565                 break;
6566         case RENDERPATH_D3D9:
6567         case RENDERPATH_D3D10:
6568         case RENDERPATH_D3D11:
6569                 for (i = 0;i < 4;i++)
6570                 {
6571                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6572                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6573                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6574                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6575                 }
6576                 break;
6577         }
6578
6579         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6580
6581         if (r_fb.fbo)
6582                 r_refdef.view.clear = true;
6583 }
6584
6585 static void R_Bloom_MakeTexture(void)
6586 {
6587         int x, range, dir;
6588         float xoffset, yoffset, r, brighten;
6589         rtexture_t *intex;
6590         float colorscale = r_bloom_colorscale.value;
6591
6592         r_refdef.stats[r_stat_bloom]++;
6593     
6594 #if 0
6595     // this copy is unnecessary since it happens in R_BlendView already
6596         if (!r_fb.fbo)
6597         {
6598                 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);
6599                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6600         }
6601 #endif
6602
6603         // scale down screen texture to the bloom texture size
6604         CHECKGLERROR
6605         r_fb.bloomindex = 0;
6606         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6607         R_SetViewport(&r_fb.bloomviewport);
6608         GL_DepthTest(false);
6609         GL_BlendFunc(GL_ONE, GL_ZERO);
6610         GL_Color(colorscale, colorscale, colorscale, 1);
6611         // 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...
6612         switch(vid.renderpath)
6613         {
6614         case RENDERPATH_GL11:
6615         case RENDERPATH_GL13:
6616         case RENDERPATH_GL20:
6617         case RENDERPATH_GLES1:
6618         case RENDERPATH_GLES2:
6619         case RENDERPATH_SOFT:
6620                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6621                 break;
6622         case RENDERPATH_D3D9:
6623         case RENDERPATH_D3D10:
6624         case RENDERPATH_D3D11:
6625                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6626                 break;
6627         }
6628         // TODO: do boxfilter scale-down in shader?
6629         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6630         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6631         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6632
6633         // we now have a properly scaled bloom image
6634         if (!r_fb.bloomfbo[r_fb.bloomindex])
6635         {
6636                 // copy it into the bloom texture
6637                 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);
6638                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6639         }
6640
6641         // multiply bloom image by itself as many times as desired
6642         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6643         {
6644                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6645                 r_fb.bloomindex ^= 1;
6646                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6647                 x *= 2;
6648                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6649                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6650                 {
6651                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6652                         GL_Color(r,r,r,1); // apply fix factor
6653                 }
6654                 else
6655                 {
6656                         if(x <= 2)
6657                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6658                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6659                         GL_Color(1,1,1,1); // no fix factor supported here
6660                 }
6661                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6662                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6663                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6664                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6665
6666                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6667                 {
6668                         // copy the darkened image to a texture
6669                         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);
6670                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6671                 }
6672         }
6673
6674         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6675         brighten = r_bloom_brighten.value;
6676         brighten = sqrt(brighten);
6677         if(range >= 1)
6678                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6679
6680         for (dir = 0;dir < 2;dir++)
6681         {
6682                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6683                 r_fb.bloomindex ^= 1;
6684                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6685                 // blend on at multiple vertical offsets to achieve a vertical blur
6686                 // TODO: do offset blends using GLSL
6687                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6688                 GL_BlendFunc(GL_ONE, GL_ZERO);
6689                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6690                 for (x = -range;x <= range;x++)
6691                 {
6692                         if (!dir){xoffset = 0;yoffset = x;}
6693                         else {xoffset = x;yoffset = 0;}
6694                         xoffset /= (float)r_fb.bloomtexturewidth;
6695                         yoffset /= (float)r_fb.bloomtextureheight;
6696                         // compute a texcoord array with the specified x and y offset
6697                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6698                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6699                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6700                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6701                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6702                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6703                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6704                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6705                         // this r value looks like a 'dot' particle, fading sharply to
6706                         // black at the edges
6707                         // (probably not realistic but looks good enough)
6708                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6709                         //r = brighten/(range*2+1);
6710                         r = brighten / (range * 2 + 1);
6711                         if(range >= 1)
6712                                 r *= (1 - x*x/(float)(range*range));
6713                         GL_Color(r, r, r, 1);
6714                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6715                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6716                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6717                         GL_BlendFunc(GL_ONE, GL_ONE);
6718                 }
6719
6720                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6721                 {
6722                         // copy the vertically or horizontally blurred bloom view to a texture
6723                         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);
6724                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6725                 }
6726         }
6727 }
6728
6729 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6730 {
6731         unsigned int permutation;
6732         float uservecs[4][4];
6733
6734         R_EntityMatrix(&identitymatrix);
6735
6736         switch (vid.renderpath)
6737         {
6738         case RENDERPATH_GL20:
6739         case RENDERPATH_D3D9:
6740         case RENDERPATH_D3D10:
6741         case RENDERPATH_D3D11:
6742         case RENDERPATH_SOFT:
6743         case RENDERPATH_GLES2:
6744                 permutation =
6745                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6746                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6747                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6748                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6749                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6750
6751                 if (r_fb.colortexture)
6752                 {
6753                         if (!r_fb.fbo)
6754                         {
6755                                 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);
6756                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6757                         }
6758
6759                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6760                         {
6761                                 // declare variables
6762                                 float blur_factor, blur_mouseaccel, blur_velocity;
6763                                 static float blur_average; 
6764                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6765
6766                                 // set a goal for the factoring
6767                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6768                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6769                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6770                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6771                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6772                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6773
6774                                 // from the goal, pick an averaged value between goal and last value
6775                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6776                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6777
6778                                 // enforce minimum amount of blur 
6779                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6780
6781                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6782
6783                                 // calculate values into a standard alpha
6784                                 cl.motionbluralpha = 1 - exp(-
6785                                                 (
6786                                                  (r_motionblur.value * blur_factor / 80)
6787                                                  +
6788                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6789                                                 )
6790                                                 /
6791                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6792                                           );
6793
6794                                 // randomization for the blur value to combat persistent ghosting
6795                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6796                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6797
6798                                 // apply the blur
6799                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6800                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6801                                 {
6802                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6803                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6804                                         switch(vid.renderpath)
6805                                         {
6806                                         case RENDERPATH_GL11:
6807                                         case RENDERPATH_GL13:
6808                                         case RENDERPATH_GL20:
6809                                         case RENDERPATH_GLES1:
6810                                         case RENDERPATH_GLES2:
6811                                         case RENDERPATH_SOFT:
6812                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6813                                                 break;
6814                                         case RENDERPATH_D3D9:
6815                                         case RENDERPATH_D3D10:
6816                                         case RENDERPATH_D3D11:
6817                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6818                                                 break;
6819                                         }
6820                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6821                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6822                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6823                                 }
6824
6825                                 // updates old view angles for next pass
6826                                 VectorCopy(cl.viewangles, blur_oldangles);
6827
6828                                 // copy view into the ghost texture
6829                                 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);
6830                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6831                                 r_fb.ghosttexture_valid = true;
6832                         }
6833                 }
6834                 else
6835                 {
6836                         // no r_fb.colortexture means we're rendering to the real fb
6837                         // we may still have to do view tint...
6838                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6839                         {
6840                                 // apply a color tint to the whole view
6841                                 R_ResetViewRendering2D(0, NULL, NULL);
6842                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6843                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6844                                 R_SetupShader_Generic_NoTexture(false, true);
6845                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6846                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6847                         }
6848                         break; // no screen processing, no bloom, skip it
6849                 }
6850
6851                 if (r_fb.bloomtexture[0])
6852                 {
6853                         // make the bloom texture
6854                         R_Bloom_MakeTexture();
6855                 }
6856
6857 #if _MSC_VER >= 1400
6858 #define sscanf sscanf_s
6859 #endif
6860                 memset(uservecs, 0, sizeof(uservecs));
6861                 if (r_glsl_postprocess_uservec1_enable.integer)
6862                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6863                 if (r_glsl_postprocess_uservec2_enable.integer)
6864                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6865                 if (r_glsl_postprocess_uservec3_enable.integer)
6866                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6867                 if (r_glsl_postprocess_uservec4_enable.integer)
6868                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6869
6870                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6871                 GL_Color(1, 1, 1, 1);
6872                 GL_BlendFunc(GL_ONE, GL_ZERO);
6873
6874                 switch(vid.renderpath)
6875                 {
6876                 case RENDERPATH_GL20:
6877                 case RENDERPATH_GLES2:
6878                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6879                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6880                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6881                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6882                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6883                         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]);
6884                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6885                         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]);
6886                         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]);
6887                         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]);
6888                         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]);
6889                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6890                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6891                         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);
6892                         break;
6893                 case RENDERPATH_D3D9:
6894 #ifdef SUPPORTD3D
6895                         // 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...
6896                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6897                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6898                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6899                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6900                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6901                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6902                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6903                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6904                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6905                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6906                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6907                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6908                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6909                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6910 #endif
6911                         break;
6912                 case RENDERPATH_D3D10:
6913                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6914                         break;
6915                 case RENDERPATH_D3D11:
6916                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6917                         break;
6918                 case RENDERPATH_SOFT:
6919                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6920                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6921                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6922                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6923                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6924                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6925                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6926                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6927                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6928                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6929                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6930                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6931                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6932                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6933                         break;
6934                 default:
6935                         break;
6936                 }
6937                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6938                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6939                 break;
6940         case RENDERPATH_GL11:
6941         case RENDERPATH_GL13:
6942         case RENDERPATH_GLES1:
6943                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6944                 {
6945                         // apply a color tint to the whole view
6946                         R_ResetViewRendering2D(0, NULL, NULL);
6947                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6948                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6949                         R_SetupShader_Generic_NoTexture(false, true);
6950                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6951                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6952                 }
6953                 break;
6954         }
6955 }
6956
6957 matrix4x4_t r_waterscrollmatrix;
6958
6959 void R_UpdateFog(void)
6960 {
6961         // Nehahra fog
6962         if (gamemode == GAME_NEHAHRA)
6963         {
6964                 if (gl_fogenable.integer)
6965                 {
6966                         r_refdef.oldgl_fogenable = true;
6967                         r_refdef.fog_density = gl_fogdensity.value;
6968                         r_refdef.fog_red = gl_fogred.value;
6969                         r_refdef.fog_green = gl_foggreen.value;
6970                         r_refdef.fog_blue = gl_fogblue.value;
6971                         r_refdef.fog_alpha = 1;
6972                         r_refdef.fog_start = 0;
6973                         r_refdef.fog_end = gl_skyclip.value;
6974                         r_refdef.fog_height = 1<<30;
6975                         r_refdef.fog_fadedepth = 128;
6976                 }
6977                 else if (r_refdef.oldgl_fogenable)
6978                 {
6979                         r_refdef.oldgl_fogenable = false;
6980                         r_refdef.fog_density = 0;
6981                         r_refdef.fog_red = 0;
6982                         r_refdef.fog_green = 0;
6983                         r_refdef.fog_blue = 0;
6984                         r_refdef.fog_alpha = 0;
6985                         r_refdef.fog_start = 0;
6986                         r_refdef.fog_end = 0;
6987                         r_refdef.fog_height = 1<<30;
6988                         r_refdef.fog_fadedepth = 128;
6989                 }
6990         }
6991
6992         // fog parms
6993         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6994         r_refdef.fog_start = max(0, r_refdef.fog_start);
6995         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6996
6997         if (r_refdef.fog_density && r_drawfog.integer)
6998         {
6999                 r_refdef.fogenabled = true;
7000                 // this is the point where the fog reaches 0.9986 alpha, which we
7001                 // consider a good enough cutoff point for the texture
7002                 // (0.9986 * 256 == 255.6)
7003                 if (r_fog_exp2.integer)
7004                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7005                 else
7006                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7007                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7008                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7009                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7010                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7011                         R_BuildFogHeightTexture();
7012                 // fog color was already set
7013                 // update the fog texture
7014                 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)
7015                         R_BuildFogTexture();
7016                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7017                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7018         }
7019         else
7020                 r_refdef.fogenabled = false;
7021
7022         // fog color
7023         if (r_refdef.fog_density)
7024         {
7025                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7026                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7027                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7028
7029                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7030                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7031                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7032                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7033
7034                 {
7035                         vec3_t fogvec;
7036                         VectorCopy(r_refdef.fogcolor, fogvec);
7037                         //   color.rgb *= ContrastBoost * SceneBrightness;
7038                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7039                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7040                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7041                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7042                 }
7043         }
7044 }
7045
7046 void R_UpdateVariables(void)
7047 {
7048         R_Textures_Frame();
7049
7050         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7051
7052         r_refdef.farclip = r_farclip_base.value;
7053         if (r_refdef.scene.worldmodel)
7054                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7055         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7056
7057         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7058                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7059         r_refdef.polygonfactor = 0;
7060         r_refdef.polygonoffset = 0;
7061         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7062         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7063
7064         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7065         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7066         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7067         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7068         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7069         if (FAKELIGHT_ENABLED)
7070         {
7071                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7072         }
7073         else if (r_refdef.scene.worldmodel)
7074         {
7075                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7076         }
7077         if (r_showsurfaces.integer)
7078         {
7079                 r_refdef.scene.rtworld = false;
7080                 r_refdef.scene.rtworldshadows = false;
7081                 r_refdef.scene.rtdlight = false;
7082                 r_refdef.scene.rtdlightshadows = false;
7083                 r_refdef.lightmapintensity = 0;
7084         }
7085
7086         r_gpuskeletal = false;
7087         switch(vid.renderpath)
7088         {
7089         case RENDERPATH_GL20:
7090                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7091         case RENDERPATH_D3D9:
7092         case RENDERPATH_D3D10:
7093         case RENDERPATH_D3D11:
7094         case RENDERPATH_SOFT:
7095         case RENDERPATH_GLES2:
7096                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7097                 {
7098                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7099                         {
7100                                 // build GLSL gamma texture
7101 #define RAMPWIDTH 256
7102                                 unsigned short ramp[RAMPWIDTH * 3];
7103                                 unsigned char rampbgr[RAMPWIDTH][4];
7104                                 int i;
7105
7106                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7107
7108                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7109                                 for(i = 0; i < RAMPWIDTH; ++i)
7110                                 {
7111                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7112                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7113                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7114                                         rampbgr[i][3] = 0;
7115                                 }
7116                                 if (r_texture_gammaramps)
7117                                 {
7118                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7119                                 }
7120                                 else
7121                                 {
7122                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7123                                 }
7124                         }
7125                 }
7126                 else
7127                 {
7128                         // remove GLSL gamma texture
7129                 }
7130                 break;
7131         case RENDERPATH_GL11:
7132         case RENDERPATH_GL13:
7133         case RENDERPATH_GLES1:
7134                 break;
7135         }
7136 }
7137
7138 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7139 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7140 /*
7141 ================
7142 R_SelectScene
7143 ================
7144 */
7145 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7146         if( scenetype != r_currentscenetype ) {
7147                 // store the old scenetype
7148                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7149                 r_currentscenetype = scenetype;
7150                 // move in the new scene
7151                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7152         }
7153 }
7154
7155 /*
7156 ================
7157 R_GetScenePointer
7158 ================
7159 */
7160 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7161 {
7162         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7163         if( scenetype == r_currentscenetype ) {
7164                 return &r_refdef.scene;
7165         } else {
7166                 return &r_scenes_store[ scenetype ];
7167         }
7168 }
7169
7170 static int R_SortEntities_Compare(const void *ap, const void *bp)
7171 {
7172         const entity_render_t *a = *(const entity_render_t **)ap;
7173         const entity_render_t *b = *(const entity_render_t **)bp;
7174
7175         // 1. compare model
7176         if(a->model < b->model)
7177                 return -1;
7178         if(a->model > b->model)
7179                 return +1;
7180
7181         // 2. compare skin
7182         // TODO possibly calculate the REAL skinnum here first using
7183         // skinscenes?
7184         if(a->skinnum < b->skinnum)
7185                 return -1;
7186         if(a->skinnum > b->skinnum)
7187                 return +1;
7188
7189         // everything we compared is equal
7190         return 0;
7191 }
7192 static void R_SortEntities(void)
7193 {
7194         // below or equal 2 ents, sorting never gains anything
7195         if(r_refdef.scene.numentities <= 2)
7196                 return;
7197         // sort
7198         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7199 }
7200
7201 /*
7202 ================
7203 R_RenderView
7204 ================
7205 */
7206 int dpsoftrast_test;
7207 extern cvar_t r_shadow_bouncegrid;
7208 void R_RenderView(void)
7209 {
7210         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7211         int fbo;
7212         rtexture_t *depthtexture;
7213         rtexture_t *colortexture;
7214
7215         dpsoftrast_test = r_test.integer;
7216
7217         if (r_timereport_active)
7218                 R_TimeReport("start");
7219         r_textureframe++; // used only by R_GetCurrentTexture
7220         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7221
7222         if(R_CompileShader_CheckStaticParms())
7223                 R_GLSL_Restart_f();
7224
7225         if (!r_drawentities.integer)
7226                 r_refdef.scene.numentities = 0;
7227         else if (r_sortentities.integer)
7228                 R_SortEntities();
7229
7230         R_AnimCache_ClearCache();
7231
7232         /* adjust for stereo display */
7233         if(R_Stereo_Active())
7234         {
7235                 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);
7236                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7237         }
7238
7239         if (r_refdef.view.isoverlay)
7240         {
7241                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7242                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7243                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7244                 R_TimeReport("depthclear");
7245
7246                 r_refdef.view.showdebug = false;
7247
7248                 r_fb.water.enabled = false;
7249                 r_fb.water.numwaterplanes = 0;
7250
7251                 R_RenderScene(0, NULL, NULL);
7252
7253                 r_refdef.view.matrix = originalmatrix;
7254
7255                 CHECKGLERROR
7256                 return;
7257         }
7258
7259         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7260         {
7261                 r_refdef.view.matrix = originalmatrix;
7262                 return;
7263         }
7264
7265         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7266
7267         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7268                 // in sRGB fallback, behave similar to true sRGB: convert this
7269                 // value from linear to sRGB
7270                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7271
7272         R_RenderView_UpdateViewVectors();
7273
7274         R_Shadow_UpdateWorldLightSelection();
7275
7276         R_Bloom_StartFrame();
7277
7278         // apply bloom brightness offset
7279         if(r_fb.bloomtexture[0])
7280                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7281
7282         R_Water_StartFrame();
7283
7284         // now we probably have an fbo to render into
7285         fbo = r_fb.fbo;
7286         depthtexture = r_fb.depthtexture;
7287         colortexture = r_fb.colortexture;
7288
7289         CHECKGLERROR
7290         if (r_timereport_active)
7291                 R_TimeReport("viewsetup");
7292
7293         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7294
7295         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7296         {
7297                 R_ClearScreen(r_refdef.fogenabled);
7298                 if (r_timereport_active)
7299                         R_TimeReport("viewclear");
7300         }
7301         r_refdef.view.clear = true;
7302
7303         r_refdef.view.showdebug = true;
7304
7305         R_View_Update();
7306         if (r_timereport_active)
7307                 R_TimeReport("visibility");
7308
7309         R_AnimCache_CacheVisibleEntities();
7310         if (r_timereport_active)
7311                 R_TimeReport("animcache");
7312
7313         R_Shadow_UpdateBounceGridTexture();
7314         if (r_timereport_active && r_shadow_bouncegrid.integer)
7315                 R_TimeReport("bouncegrid");
7316
7317         r_fb.water.numwaterplanes = 0;
7318         if (r_fb.water.enabled)
7319                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7320
7321         R_RenderScene(fbo, depthtexture, colortexture);
7322         r_fb.water.numwaterplanes = 0;
7323
7324         R_BlendView(fbo, depthtexture, colortexture);
7325         if (r_timereport_active)
7326                 R_TimeReport("blendview");
7327
7328         GL_Scissor(0, 0, vid.width, vid.height);
7329         GL_ScissorTest(false);
7330
7331         r_refdef.view.matrix = originalmatrix;
7332
7333         CHECKGLERROR
7334 }
7335
7336 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7337 {
7338         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7339         {
7340                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7341                 if (r_timereport_active)
7342                         R_TimeReport("waterworld");
7343         }
7344
7345         // don't let sound skip if going slow
7346         if (r_refdef.scene.extraupdate)
7347                 S_ExtraUpdate ();
7348
7349         R_DrawModelsAddWaterPlanes();
7350         if (r_timereport_active)
7351                 R_TimeReport("watermodels");
7352
7353         if (r_fb.water.numwaterplanes)
7354         {
7355                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7356                 if (r_timereport_active)
7357                         R_TimeReport("waterscenes");
7358         }
7359 }
7360
7361 extern cvar_t cl_locs_show;
7362 static void R_DrawLocs(void);
7363 static void R_DrawEntityBBoxes(void);
7364 static void R_DrawModelDecals(void);
7365 extern cvar_t cl_decals_newsystem;
7366 extern qboolean r_shadow_usingdeferredprepass;
7367 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7368 {
7369         qboolean shadowmapping = false;
7370
7371         if (r_timereport_active)
7372                 R_TimeReport("beginscene");
7373
7374         r_refdef.stats[r_stat_renders]++;
7375
7376         R_UpdateFog();
7377
7378         // don't let sound skip if going slow
7379         if (r_refdef.scene.extraupdate)
7380                 S_ExtraUpdate ();
7381
7382         R_MeshQueue_BeginScene();
7383
7384         R_SkyStartFrame();
7385
7386         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);
7387
7388         if (r_timereport_active)
7389                 R_TimeReport("skystartframe");
7390
7391         if (cl.csqc_vidvars.drawworld)
7392         {
7393                 // don't let sound skip if going slow
7394                 if (r_refdef.scene.extraupdate)
7395                         S_ExtraUpdate ();
7396
7397                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7398                 {
7399                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7400                         if (r_timereport_active)
7401                                 R_TimeReport("worldsky");
7402                 }
7403
7404                 if (R_DrawBrushModelsSky() && r_timereport_active)
7405                         R_TimeReport("bmodelsky");
7406
7407                 if (skyrendermasked && skyrenderlater)
7408                 {
7409                         // we have to force off the water clipping plane while rendering sky
7410                         R_SetupView(false, fbo, depthtexture, colortexture);
7411                         R_Sky();
7412                         R_SetupView(true, fbo, depthtexture, colortexture);
7413                         if (r_timereport_active)
7414                                 R_TimeReport("sky");
7415                 }
7416         }
7417
7418         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7419         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7420                 R_Shadow_PrepareModelShadows();
7421         if (r_timereport_active)
7422                 R_TimeReport("preparelights");
7423
7424         if (R_Shadow_ShadowMappingEnabled())
7425                 shadowmapping = true;
7426
7427         if (r_shadow_usingdeferredprepass)
7428                 R_Shadow_DrawPrepass();
7429
7430         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7431         {
7432                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7433                 if (r_timereport_active)
7434                         R_TimeReport("worlddepth");
7435         }
7436         if (r_depthfirst.integer >= 2)
7437         {
7438                 R_DrawModelsDepth();
7439                 if (r_timereport_active)
7440                         R_TimeReport("modeldepth");
7441         }
7442
7443         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7444         {
7445                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7446                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7447                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7448                 // don't let sound skip if going slow
7449                 if (r_refdef.scene.extraupdate)
7450                         S_ExtraUpdate ();
7451         }
7452
7453         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7454         {
7455                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7456                 if (r_timereport_active)
7457                         R_TimeReport("world");
7458         }
7459
7460         // don't let sound skip if going slow
7461         if (r_refdef.scene.extraupdate)
7462                 S_ExtraUpdate ();
7463
7464         R_DrawModels();
7465         if (r_timereport_active)
7466                 R_TimeReport("models");
7467
7468         // don't let sound skip if going slow
7469         if (r_refdef.scene.extraupdate)
7470                 S_ExtraUpdate ();
7471
7472         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7473         {
7474                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7475                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7476                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7477                 // don't let sound skip if going slow
7478                 if (r_refdef.scene.extraupdate)
7479                         S_ExtraUpdate ();
7480         }
7481
7482         if (!r_shadow_usingdeferredprepass)
7483         {
7484                 R_Shadow_DrawLights();
7485                 if (r_timereport_active)
7486                         R_TimeReport("rtlights");
7487         }
7488
7489         // don't let sound skip if going slow
7490         if (r_refdef.scene.extraupdate)
7491                 S_ExtraUpdate ();
7492
7493         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7494         {
7495                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7496                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7497                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7498                 // don't let sound skip if going slow
7499                 if (r_refdef.scene.extraupdate)
7500                         S_ExtraUpdate ();
7501         }
7502
7503         if (cl.csqc_vidvars.drawworld)
7504         {
7505                 if (cl_decals_newsystem.integer)
7506                 {
7507                         R_DrawModelDecals();
7508                         if (r_timereport_active)
7509                                 R_TimeReport("modeldecals");
7510                 }
7511                 else
7512                 {
7513                         R_DrawDecals();
7514                         if (r_timereport_active)
7515                                 R_TimeReport("decals");
7516                 }
7517
7518                 R_DrawParticles();
7519                 if (r_timereport_active)
7520                         R_TimeReport("particles");
7521
7522                 R_DrawExplosions();
7523                 if (r_timereport_active)
7524                         R_TimeReport("explosions");
7525
7526                 R_DrawLightningBeams();
7527                 if (r_timereport_active)
7528                         R_TimeReport("lightning");
7529         }
7530
7531         if (cl.csqc_loaded)
7532                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7533
7534         if (r_refdef.view.showdebug)
7535         {
7536                 if (cl_locs_show.integer)
7537                 {
7538                         R_DrawLocs();
7539                         if (r_timereport_active)
7540                                 R_TimeReport("showlocs");
7541                 }
7542
7543                 if (r_drawportals.integer)
7544                 {
7545                         R_DrawPortals();
7546                         if (r_timereport_active)
7547                                 R_TimeReport("portals");
7548                 }
7549
7550                 if (r_showbboxes.value > 0)
7551                 {
7552                         R_DrawEntityBBoxes();
7553                         if (r_timereport_active)
7554                                 R_TimeReport("bboxes");
7555                 }
7556         }
7557
7558         if (r_transparent.integer)
7559         {
7560                 R_MeshQueue_RenderTransparent();
7561                 if (r_timereport_active)
7562                         R_TimeReport("drawtrans");
7563         }
7564
7565         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))
7566         {
7567                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7568                 if (r_timereport_active)
7569                         R_TimeReport("worlddebug");
7570                 R_DrawModelsDebug();
7571                 if (r_timereport_active)
7572                         R_TimeReport("modeldebug");
7573         }
7574
7575         if (cl.csqc_vidvars.drawworld)
7576         {
7577                 R_Shadow_DrawCoronas();
7578                 if (r_timereport_active)
7579                         R_TimeReport("coronas");
7580         }
7581
7582 #if 0
7583         {
7584                 GL_DepthTest(false);
7585                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7586                 GL_Color(1, 1, 1, 1);
7587                 qglBegin(GL_POLYGON);
7588                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7589                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7590                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7591                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7592                 qglEnd();
7593                 qglBegin(GL_POLYGON);
7594                 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]);
7595                 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]);
7596                 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]);
7597                 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]);
7598                 qglEnd();
7599                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7600         }
7601 #endif
7602
7603         // don't let sound skip if going slow
7604         if (r_refdef.scene.extraupdate)
7605                 S_ExtraUpdate ();
7606 }
7607
7608 static const unsigned short bboxelements[36] =
7609 {
7610         5, 1, 3, 5, 3, 7,
7611         6, 2, 0, 6, 0, 4,
7612         7, 3, 2, 7, 2, 6,
7613         4, 0, 1, 4, 1, 5,
7614         4, 5, 7, 4, 7, 6,
7615         1, 0, 2, 1, 2, 3,
7616 };
7617
7618 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7619 {
7620         int i;
7621         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7622
7623         RSurf_ActiveWorldEntity();
7624
7625         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7626         GL_DepthMask(false);
7627         GL_DepthRange(0, 1);
7628         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7629 //      R_Mesh_ResetTextureState();
7630
7631         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7632         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7633         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7634         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7635         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7636         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7637         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7638         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7639         R_FillColors(color4f, 8, cr, cg, cb, ca);
7640         if (r_refdef.fogenabled)
7641         {
7642                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7643                 {
7644                         f1 = RSurf_FogVertex(v);
7645                         f2 = 1 - f1;
7646                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7647                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7648                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7649                 }
7650         }
7651         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7652         R_Mesh_ResetTextureState();
7653         R_SetupShader_Generic_NoTexture(false, false);
7654         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7655 }
7656
7657 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7658 {
7659         prvm_prog_t *prog = SVVM_prog;
7660         int i;
7661         float color[4];
7662         prvm_edict_t *edict;
7663
7664         // this function draws bounding boxes of server entities
7665         if (!sv.active)
7666                 return;
7667
7668         GL_CullFace(GL_NONE);
7669         R_SetupShader_Generic_NoTexture(false, false);
7670
7671         for (i = 0;i < numsurfaces;i++)
7672         {
7673                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7674                 switch ((int)PRVM_serveredictfloat(edict, solid))
7675                 {
7676                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7677                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7678                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7679                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7680                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7681                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7682                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7683                 }
7684                 color[3] *= r_showbboxes.value;
7685                 color[3] = bound(0, color[3], 1);
7686                 GL_DepthTest(!r_showdisabledepthtest.integer);
7687                 GL_CullFace(r_refdef.view.cullface_front);
7688                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7689         }
7690 }
7691
7692 static void R_DrawEntityBBoxes(void)
7693 {
7694         int i;
7695         prvm_edict_t *edict;
7696         vec3_t center;
7697         prvm_prog_t *prog = SVVM_prog;
7698
7699         // this function draws bounding boxes of server entities
7700         if (!sv.active)
7701                 return;
7702
7703         for (i = 0;i < prog->num_edicts;i++)
7704         {
7705                 edict = PRVM_EDICT_NUM(i);
7706                 if (edict->priv.server->free)
7707                         continue;
7708                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7709                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7710                         continue;
7711                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7712                         continue;
7713                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7714                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7715         }
7716 }
7717
7718 static const int nomodelelement3i[24] =
7719 {
7720         5, 2, 0,
7721         5, 1, 2,
7722         5, 0, 3,
7723         5, 3, 1,
7724         0, 2, 4,
7725         2, 1, 4,
7726         3, 0, 4,
7727         1, 3, 4
7728 };
7729
7730 static const unsigned short nomodelelement3s[24] =
7731 {
7732         5, 2, 0,
7733         5, 1, 2,
7734         5, 0, 3,
7735         5, 3, 1,
7736         0, 2, 4,
7737         2, 1, 4,
7738         3, 0, 4,
7739         1, 3, 4
7740 };
7741
7742 static const float nomodelvertex3f[6*3] =
7743 {
7744         -16,   0,   0,
7745          16,   0,   0,
7746           0, -16,   0,
7747           0,  16,   0,
7748           0,   0, -16,
7749           0,   0,  16
7750 };
7751
7752 static const float nomodelcolor4f[6*4] =
7753 {
7754         0.0f, 0.0f, 0.5f, 1.0f,
7755         0.0f, 0.0f, 0.5f, 1.0f,
7756         0.0f, 0.5f, 0.0f, 1.0f,
7757         0.0f, 0.5f, 0.0f, 1.0f,
7758         0.5f, 0.0f, 0.0f, 1.0f,
7759         0.5f, 0.0f, 0.0f, 1.0f
7760 };
7761
7762 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7763 {
7764         int i;
7765         float f1, f2, *c;
7766         float color4f[6*4];
7767
7768         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);
7769
7770         // this is only called once per entity so numsurfaces is always 1, and
7771         // surfacelist is always {0}, so this code does not handle batches
7772
7773         if (rsurface.ent_flags & RENDER_ADDITIVE)
7774         {
7775                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7776                 GL_DepthMask(false);
7777         }
7778         else if (rsurface.colormod[3] < 1)
7779         {
7780                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7781                 GL_DepthMask(false);
7782         }
7783         else
7784         {
7785                 GL_BlendFunc(GL_ONE, GL_ZERO);
7786                 GL_DepthMask(true);
7787         }
7788         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7789         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7790         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7791         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7792         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7793         for (i = 0, c = color4f;i < 6;i++, c += 4)
7794         {
7795                 c[0] *= rsurface.colormod[0];
7796                 c[1] *= rsurface.colormod[1];
7797                 c[2] *= rsurface.colormod[2];
7798                 c[3] *= rsurface.colormod[3];
7799         }
7800         if (r_refdef.fogenabled)
7801         {
7802                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7803                 {
7804                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7805                         f2 = 1 - f1;
7806                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7807                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7808                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7809                 }
7810         }
7811 //      R_Mesh_ResetTextureState();
7812         R_SetupShader_Generic_NoTexture(false, false);
7813         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7814         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7815 }
7816
7817 void R_DrawNoModel(entity_render_t *ent)
7818 {
7819         vec3_t org;
7820         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7821         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7822                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7823         else
7824                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7825 }
7826
7827 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7828 {
7829         vec3_t right1, right2, diff, normal;
7830
7831         VectorSubtract (org2, org1, normal);
7832
7833         // calculate 'right' vector for start
7834         VectorSubtract (r_refdef.view.origin, org1, diff);
7835         CrossProduct (normal, diff, right1);
7836         VectorNormalize (right1);
7837
7838         // calculate 'right' vector for end
7839         VectorSubtract (r_refdef.view.origin, org2, diff);
7840         CrossProduct (normal, diff, right2);
7841         VectorNormalize (right2);
7842
7843         vert[ 0] = org1[0] + width * right1[0];
7844         vert[ 1] = org1[1] + width * right1[1];
7845         vert[ 2] = org1[2] + width * right1[2];
7846         vert[ 3] = org1[0] - width * right1[0];
7847         vert[ 4] = org1[1] - width * right1[1];
7848         vert[ 5] = org1[2] - width * right1[2];
7849         vert[ 6] = org2[0] - width * right2[0];
7850         vert[ 7] = org2[1] - width * right2[1];
7851         vert[ 8] = org2[2] - width * right2[2];
7852         vert[ 9] = org2[0] + width * right2[0];
7853         vert[10] = org2[1] + width * right2[1];
7854         vert[11] = org2[2] + width * right2[2];
7855 }
7856
7857 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)
7858 {
7859         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7860         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7861         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7862         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7863         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7864         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7865         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7866         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7867         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7868         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7869         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7870         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7871 }
7872
7873 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7874 {
7875         int i;
7876         float *vertex3f;
7877         float v[3];
7878         VectorSet(v, x, y, z);
7879         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7880                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7881                         break;
7882         if (i == mesh->numvertices)
7883         {
7884                 if (mesh->numvertices < mesh->maxvertices)
7885                 {
7886                         VectorCopy(v, vertex3f);
7887                         mesh->numvertices++;
7888                 }
7889                 return mesh->numvertices;
7890         }
7891         else
7892                 return i;
7893 }
7894
7895 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7896 {
7897         int i;
7898         int *e, element[3];
7899         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7900         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7901         e = mesh->element3i + mesh->numtriangles * 3;
7902         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7903         {
7904                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7905                 if (mesh->numtriangles < mesh->maxtriangles)
7906                 {
7907                         *e++ = element[0];
7908                         *e++ = element[1];
7909                         *e++ = element[2];
7910                         mesh->numtriangles++;
7911                 }
7912                 element[1] = element[2];
7913         }
7914 }
7915
7916 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7917 {
7918         int i;
7919         int *e, element[3];
7920         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7921         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7922         e = mesh->element3i + mesh->numtriangles * 3;
7923         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7924         {
7925                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7926                 if (mesh->numtriangles < mesh->maxtriangles)
7927                 {
7928                         *e++ = element[0];
7929                         *e++ = element[1];
7930                         *e++ = element[2];
7931                         mesh->numtriangles++;
7932                 }
7933                 element[1] = element[2];
7934         }
7935 }
7936
7937 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7938 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7939 {
7940         int planenum, planenum2;
7941         int w;
7942         int tempnumpoints;
7943         mplane_t *plane, *plane2;
7944         double maxdist;
7945         double temppoints[2][256*3];
7946         // figure out how large a bounding box we need to properly compute this brush
7947         maxdist = 0;
7948         for (w = 0;w < numplanes;w++)
7949                 maxdist = max(maxdist, fabs(planes[w].dist));
7950         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7951         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7952         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7953         {
7954                 w = 0;
7955                 tempnumpoints = 4;
7956                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7957                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7958                 {
7959                         if (planenum2 == planenum)
7960                                 continue;
7961                         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);
7962                         w = !w;
7963                 }
7964                 if (tempnumpoints < 3)
7965                         continue;
7966                 // generate elements forming a triangle fan for this polygon
7967                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7968         }
7969 }
7970
7971 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)
7972 {
7973         texturelayer_t *layer;
7974         layer = t->currentlayers + t->currentnumlayers++;
7975         layer->type = type;
7976         layer->depthmask = depthmask;
7977         layer->blendfunc1 = blendfunc1;
7978         layer->blendfunc2 = blendfunc2;
7979         layer->texture = texture;
7980         layer->texmatrix = *matrix;
7981         layer->color[0] = r;
7982         layer->color[1] = g;
7983         layer->color[2] = b;
7984         layer->color[3] = a;
7985 }
7986
7987 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7988 {
7989         if(parms[0] == 0 && parms[1] == 0)
7990                 return false;
7991         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7992                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7993                         return false;
7994         return true;
7995 }
7996
7997 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7998 {
7999         double index, f;
8000         index = parms[2] + rsurface.shadertime * parms[3];
8001         index -= floor(index);
8002         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8003         {
8004         default:
8005         case Q3WAVEFUNC_NONE:
8006         case Q3WAVEFUNC_NOISE:
8007         case Q3WAVEFUNC_COUNT:
8008                 f = 0;
8009                 break;
8010         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8011         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8012         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8013         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8014         case Q3WAVEFUNC_TRIANGLE:
8015                 index *= 4;
8016                 f = index - floor(index);
8017                 if (index < 1)
8018                 {
8019                         // f = f;
8020                 }
8021                 else if (index < 2)
8022                         f = 1 - f;
8023                 else if (index < 3)
8024                         f = -f;
8025                 else
8026                         f = -(1 - f);
8027                 break;
8028         }
8029         f = parms[0] + parms[1] * f;
8030         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8031                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8032         return (float) f;
8033 }
8034
8035 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8036 {
8037         int w, h, idx;
8038         float shadertime;
8039         float f;
8040         float offsetd[2];
8041         float tcmat[12];
8042         matrix4x4_t matrix, temp;
8043         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8044         // it's better to have one huge fixup every 9 hours than gradual
8045         // degradation over time which looks consistently bad after many hours.
8046         //
8047         // tcmod scroll in particular suffers from this degradation which can't be
8048         // effectively worked around even with floor() tricks because we don't
8049         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8050         // a workaround involving floor() would be incorrect anyway...
8051         shadertime = rsurface.shadertime;
8052         if (shadertime >= 32768.0f)
8053                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8054         switch(tcmod->tcmod)
8055         {
8056                 case Q3TCMOD_COUNT:
8057                 case Q3TCMOD_NONE:
8058                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8059                                 matrix = r_waterscrollmatrix;
8060                         else
8061                                 matrix = identitymatrix;
8062                         break;
8063                 case Q3TCMOD_ENTITYTRANSLATE:
8064                         // this is used in Q3 to allow the gamecode to control texcoord
8065                         // scrolling on the entity, which is not supported in darkplaces yet.
8066                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8067                         break;
8068                 case Q3TCMOD_ROTATE:
8069                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8070                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8071                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8072                         break;
8073                 case Q3TCMOD_SCALE:
8074                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8075                         break;
8076                 case Q3TCMOD_SCROLL:
8077                         // this particular tcmod is a "bug for bug" compatible one with regards to
8078                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8079                         // specifically did the wrapping and so we must mimic that...
8080                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8081                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8082                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8083                         break;
8084                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8085                         w = (int) tcmod->parms[0];
8086                         h = (int) tcmod->parms[1];
8087                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8088                         f = f - floor(f);
8089                         idx = (int) floor(f * w * h);
8090                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8091                         break;
8092                 case Q3TCMOD_STRETCH:
8093                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8094                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8095                         break;
8096                 case Q3TCMOD_TRANSFORM:
8097                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8098                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8099                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8100                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8101                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8102                         break;
8103                 case Q3TCMOD_TURBULENT:
8104                         // this is handled in the RSurf_PrepareVertices function
8105                         matrix = identitymatrix;
8106                         break;
8107         }
8108         temp = *texmatrix;
8109         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8110 }
8111
8112 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8113 {
8114         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8115         char name[MAX_QPATH];
8116         skinframe_t *skinframe;
8117         unsigned char pixels[296*194];
8118         strlcpy(cache->name, skinname, sizeof(cache->name));
8119         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8120         if (developer_loading.integer)
8121                 Con_Printf("loading %s\n", name);
8122         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8123         if (!skinframe || !skinframe->base)
8124         {
8125                 unsigned char *f;
8126                 fs_offset_t filesize;
8127                 skinframe = NULL;
8128                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8129                 if (f)
8130                 {
8131                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8132                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8133                         Mem_Free(f);
8134                 }
8135         }
8136         cache->skinframe = skinframe;
8137 }
8138
8139 texture_t *R_GetCurrentTexture(texture_t *t)
8140 {
8141         int i;
8142         const entity_render_t *ent = rsurface.entity;
8143         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8144         q3shaderinfo_layer_tcmod_t *tcmod;
8145
8146         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8147                 return t->currentframe;
8148         t->update_lastrenderframe = r_textureframe;
8149         t->update_lastrenderentity = (void *)ent;
8150
8151         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8152                 t->camera_entity = ent->entitynumber;
8153         else
8154                 t->camera_entity = 0;
8155
8156         // switch to an alternate material if this is a q1bsp animated material
8157         {
8158                 texture_t *texture = t;
8159                 int s = rsurface.ent_skinnum;
8160                 if ((unsigned int)s >= (unsigned int)model->numskins)
8161                         s = 0;
8162                 if (model->skinscenes)
8163                 {
8164                         if (model->skinscenes[s].framecount > 1)
8165                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8166                         else
8167                                 s = model->skinscenes[s].firstframe;
8168                 }
8169                 if (s > 0)
8170                         t = t + s * model->num_surfaces;
8171                 if (t->animated)
8172                 {
8173                         // use an alternate animation if the entity's frame is not 0,
8174                         // and only if the texture has an alternate animation
8175                         if (t->animated == 2) // q2bsp
8176                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8177                         else if (rsurface.ent_alttextures && t->anim_total[1])
8178                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8179                         else
8180                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8181                 }
8182                 texture->currentframe = t;
8183         }
8184
8185         // update currentskinframe to be a qw skin or animation frame
8186         if (rsurface.ent_qwskin >= 0)
8187         {
8188                 i = rsurface.ent_qwskin;
8189                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8190                 {
8191                         r_qwskincache_size = cl.maxclients;
8192                         if (r_qwskincache)
8193                                 Mem_Free(r_qwskincache);
8194                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8195                 }
8196                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8197                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8198                 t->currentskinframe = r_qwskincache[i].skinframe;
8199                 if (t->currentskinframe == NULL)
8200                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8201         }
8202         else if (t->numskinframes >= 2)
8203                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8204         if (t->backgroundnumskinframes >= 2)
8205                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8206
8207         t->currentmaterialflags = t->basematerialflags;
8208         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8209         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8210                 t->currentalpha *= r_wateralpha.value;
8211         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8212                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8213         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8214                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8215         if (!(rsurface.ent_flags & RENDER_LIGHT))
8216                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8217         else if (FAKELIGHT_ENABLED)
8218         {
8219                 // no modellight if using fakelight for the map
8220         }
8221         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8222         {
8223                 // pick a model lighting mode
8224                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8225                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8226                 else
8227                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8228         }
8229         if (rsurface.ent_flags & RENDER_ADDITIVE)
8230                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8231         else if (t->currentalpha < 1)
8232                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8233         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8234         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8235                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8236         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8237                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8238         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8239                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8240         if (t->backgroundnumskinframes)
8241                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8242         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8243         {
8244                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8245                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8246         }
8247         else
8248                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8249         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8250         {
8251                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8252                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8253         }
8254         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8255                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8256
8257         // there is no tcmod
8258         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8259         {
8260                 t->currenttexmatrix = r_waterscrollmatrix;
8261                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8262         }
8263         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8264         {
8265                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8266                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8267         }
8268
8269         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8270                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8271         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8272                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8273
8274         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8275         if (t->currentskinframe->qpixels)
8276                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8277         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8278         if (!t->basetexture)
8279                 t->basetexture = r_texture_notexture;
8280         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8281         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8282         t->nmaptexture = t->currentskinframe->nmap;
8283         if (!t->nmaptexture)
8284                 t->nmaptexture = r_texture_blanknormalmap;
8285         t->glosstexture = r_texture_black;
8286         t->glowtexture = t->currentskinframe->glow;
8287         t->fogtexture = t->currentskinframe->fog;
8288         t->reflectmasktexture = t->currentskinframe->reflect;
8289         if (t->backgroundnumskinframes)
8290         {
8291                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8292                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8293                 t->backgroundglosstexture = r_texture_black;
8294                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8295                 if (!t->backgroundnmaptexture)
8296                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8297                 // make sure that if glow is going to be used, both textures are not NULL
8298                 if (!t->backgroundglowtexture && t->glowtexture)
8299                         t->backgroundglowtexture = r_texture_black;
8300                 if (!t->glowtexture && t->backgroundglowtexture)
8301                         t->glowtexture = r_texture_black;
8302         }
8303         else
8304         {
8305                 t->backgroundbasetexture = r_texture_white;
8306                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8307                 t->backgroundglosstexture = r_texture_black;
8308                 t->backgroundglowtexture = NULL;
8309         }
8310         t->specularpower = r_shadow_glossexponent.value;
8311         // TODO: store reference values for these in the texture?
8312         t->specularscale = 0;
8313         if (r_shadow_gloss.integer > 0)
8314         {
8315                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8316                 {
8317                         if (r_shadow_glossintensity.value > 0)
8318                         {
8319                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8320                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8321                                 t->specularscale = r_shadow_glossintensity.value;
8322                         }
8323                 }
8324                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8325                 {
8326                         t->glosstexture = r_texture_white;
8327                         t->backgroundglosstexture = r_texture_white;
8328                         t->specularscale = r_shadow_gloss2intensity.value;
8329                         t->specularpower = r_shadow_gloss2exponent.value;
8330                 }
8331         }
8332         t->specularscale *= t->specularscalemod;
8333         t->specularpower *= t->specularpowermod;
8334         t->rtlightambient = 0;
8335
8336         // lightmaps mode looks bad with dlights using actual texturing, so turn
8337         // off the colormap and glossmap, but leave the normalmap on as it still
8338         // accurately represents the shading involved
8339         if (gl_lightmaps.integer)
8340         {
8341                 t->basetexture = r_texture_grey128;
8342                 t->pantstexture = r_texture_black;
8343                 t->shirttexture = r_texture_black;
8344                 if (gl_lightmaps.integer < 2)
8345                         t->nmaptexture = r_texture_blanknormalmap;
8346                 t->glosstexture = r_texture_black;
8347                 t->glowtexture = NULL;
8348                 t->fogtexture = NULL;
8349                 t->reflectmasktexture = NULL;
8350                 t->backgroundbasetexture = NULL;
8351                 if (gl_lightmaps.integer < 2)
8352                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8353                 t->backgroundglosstexture = r_texture_black;
8354                 t->backgroundglowtexture = NULL;
8355                 t->specularscale = 0;
8356                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8357         }
8358
8359         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8360         VectorClear(t->dlightcolor);
8361         t->currentnumlayers = 0;
8362         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8363         {
8364                 int blendfunc1, blendfunc2;
8365                 qboolean depthmask;
8366                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8367                 {
8368                         blendfunc1 = GL_SRC_ALPHA;
8369                         blendfunc2 = GL_ONE;
8370                 }
8371                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8372                 {
8373                         blendfunc1 = GL_SRC_ALPHA;
8374                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8375                 }
8376                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8377                 {
8378                         blendfunc1 = t->customblendfunc[0];
8379                         blendfunc2 = t->customblendfunc[1];
8380                 }
8381                 else
8382                 {
8383                         blendfunc1 = GL_ONE;
8384                         blendfunc2 = GL_ZERO;
8385                 }
8386                 // don't colormod evilblend textures
8387                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8388                         VectorSet(t->lightmapcolor, 1, 1, 1);
8389                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8390                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8391                 {
8392                         // fullbright is not affected by r_refdef.lightmapintensity
8393                         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]);
8394                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8395                                 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]);
8396                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8397                                 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]);
8398                 }
8399                 else
8400                 {
8401                         vec3_t ambientcolor;
8402                         float colorscale;
8403                         // set the color tint used for lights affecting this surface
8404                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8405                         colorscale = 2;
8406                         // q3bsp has no lightmap updates, so the lightstylevalue that
8407                         // would normally be baked into the lightmap must be
8408                         // applied to the color
8409                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8410                         if (model->type == mod_brushq3)
8411                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8412                         colorscale *= r_refdef.lightmapintensity;
8413                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8414                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8415                         // basic lit geometry
8416                         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]);
8417                         // add pants/shirt if needed
8418                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8419                                 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]);
8420                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8421                                 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]);
8422                         // now add ambient passes if needed
8423                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8424                         {
8425                                 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]);
8426                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8427                                         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]);
8428                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8429                                         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]);
8430                         }
8431                 }
8432                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8433                         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]);
8434                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8435                 {
8436                         // if this is opaque use alpha blend which will darken the earlier
8437                         // passes cheaply.
8438                         //
8439                         // if this is an alpha blended material, all the earlier passes
8440                         // were darkened by fog already, so we only need to add the fog
8441                         // color ontop through the fog mask texture
8442                         //
8443                         // if this is an additive blended material, all the earlier passes
8444                         // were darkened by fog already, and we should not add fog color
8445                         // (because the background was not darkened, there is no fog color
8446                         // that was lost behind it).
8447                         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]);
8448                 }
8449         }
8450
8451         return t;
8452 }
8453
8454 rsurfacestate_t rsurface;
8455
8456 void RSurf_ActiveWorldEntity(void)
8457 {
8458         dp_model_t *model = r_refdef.scene.worldmodel;
8459         //if (rsurface.entity == r_refdef.scene.worldentity)
8460         //      return;
8461         rsurface.entity = r_refdef.scene.worldentity;
8462         rsurface.skeleton = NULL;
8463         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8464         rsurface.ent_skinnum = 0;
8465         rsurface.ent_qwskin = -1;
8466         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8467         rsurface.shadertime = r_refdef.scene.time;
8468         rsurface.matrix = identitymatrix;
8469         rsurface.inversematrix = identitymatrix;
8470         rsurface.matrixscale = 1;
8471         rsurface.inversematrixscale = 1;
8472         R_EntityMatrix(&identitymatrix);
8473         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8474         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8475         rsurface.fograngerecip = r_refdef.fograngerecip;
8476         rsurface.fogheightfade = r_refdef.fogheightfade;
8477         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8478         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8479         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8480         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8481         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8482         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8483         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8484         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8485         rsurface.colormod[3] = 1;
8486         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);
8487         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8488         rsurface.frameblend[0].lerp = 1;
8489         rsurface.ent_alttextures = false;
8490         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8491         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8492         rsurface.entityskeletaltransform3x4 = NULL;
8493         rsurface.entityskeletaltransform3x4buffer = NULL;
8494         rsurface.entityskeletaltransform3x4offset = 0;
8495         rsurface.entityskeletaltransform3x4size = 0;;
8496         rsurface.entityskeletalnumtransforms = 0;
8497         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8498         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8499         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8500         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8501         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8502         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8503         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8504         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8505         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8506         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8507         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8508         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8509         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8510         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8511         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8512         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8513         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8514         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8515         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8516         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8517         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8518         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8519         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8520         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8521         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8522         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8523         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8524         rsurface.modelelement3i = model->surfmesh.data_element3i;
8525         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8526         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8527         rsurface.modelelement3s = model->surfmesh.data_element3s;
8528         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8529         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8530         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8531         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8532         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8533         rsurface.modelsurfaces = model->data_surfaces;
8534         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8535         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8536         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8537         rsurface.modelgeneratedvertex = false;
8538         rsurface.batchgeneratedvertex = false;
8539         rsurface.batchfirstvertex = 0;
8540         rsurface.batchnumvertices = 0;
8541         rsurface.batchfirsttriangle = 0;
8542         rsurface.batchnumtriangles = 0;
8543         rsurface.batchvertex3f  = NULL;
8544         rsurface.batchvertex3f_vertexbuffer = NULL;
8545         rsurface.batchvertex3f_bufferoffset = 0;
8546         rsurface.batchsvector3f = NULL;
8547         rsurface.batchsvector3f_vertexbuffer = NULL;
8548         rsurface.batchsvector3f_bufferoffset = 0;
8549         rsurface.batchtvector3f = NULL;
8550         rsurface.batchtvector3f_vertexbuffer = NULL;
8551         rsurface.batchtvector3f_bufferoffset = 0;
8552         rsurface.batchnormal3f  = NULL;
8553         rsurface.batchnormal3f_vertexbuffer = NULL;
8554         rsurface.batchnormal3f_bufferoffset = 0;
8555         rsurface.batchlightmapcolor4f = NULL;
8556         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8557         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8558         rsurface.batchtexcoordtexture2f = NULL;
8559         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8560         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8561         rsurface.batchtexcoordlightmap2f = NULL;
8562         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8563         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8564         rsurface.batchskeletalindex4ub = NULL;
8565         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8566         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8567         rsurface.batchskeletalweight4ub = NULL;
8568         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8569         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8570         rsurface.batchvertexmesh = NULL;
8571         rsurface.batchvertexmesh_vertexbuffer = NULL;
8572         rsurface.batchvertexmesh_bufferoffset = 0;
8573         rsurface.batchelement3i = NULL;
8574         rsurface.batchelement3i_indexbuffer = NULL;
8575         rsurface.batchelement3i_bufferoffset = 0;
8576         rsurface.batchelement3s = NULL;
8577         rsurface.batchelement3s_indexbuffer = NULL;
8578         rsurface.batchelement3s_bufferoffset = 0;
8579         rsurface.passcolor4f = NULL;
8580         rsurface.passcolor4f_vertexbuffer = NULL;
8581         rsurface.passcolor4f_bufferoffset = 0;
8582         rsurface.forcecurrenttextureupdate = false;
8583 }
8584
8585 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8586 {
8587         dp_model_t *model = ent->model;
8588         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8589         //      return;
8590         rsurface.entity = (entity_render_t *)ent;
8591         rsurface.skeleton = ent->skeleton;
8592         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8593         rsurface.ent_skinnum = ent->skinnum;
8594         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;
8595         rsurface.ent_flags = ent->flags;
8596         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8597         rsurface.matrix = ent->matrix;
8598         rsurface.inversematrix = ent->inversematrix;
8599         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8600         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8601         R_EntityMatrix(&rsurface.matrix);
8602         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8603         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8604         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8605         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8606         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8607         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8608         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8609         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8610         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8611         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8612         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8613         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8614         rsurface.colormod[3] = ent->alpha;
8615         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8616         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8617         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8618         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8619         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8620         if (ent->model->brush.submodel && !prepass)
8621         {
8622                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8623                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8624         }
8625         // if the animcache code decided it should use the shader path, skip the deform step
8626         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8627         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8628         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8629         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8630         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8631         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8632         {
8633                 if (ent->animcache_vertex3f)
8634                 {
8635                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8636                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8637                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8638                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8639                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8640                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8641                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8642                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8643                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8644                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8645                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8646                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8647                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8648                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8649                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8650                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8651                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8652                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8653                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8654                 }
8655                 else if (wanttangents)
8656                 {
8657                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8658                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8659                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8660                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8661                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8662                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8663                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8664                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8665                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8666                         rsurface.modelvertexmesh = NULL;
8667                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8668                         rsurface.modelvertexmesh_bufferoffset = 0;
8669                         rsurface.modelvertex3f_vertexbuffer = NULL;
8670                         rsurface.modelvertex3f_bufferoffset = 0;
8671                         rsurface.modelvertex3f_vertexbuffer = 0;
8672                         rsurface.modelvertex3f_bufferoffset = 0;
8673                         rsurface.modelsvector3f_vertexbuffer = 0;
8674                         rsurface.modelsvector3f_bufferoffset = 0;
8675                         rsurface.modeltvector3f_vertexbuffer = 0;
8676                         rsurface.modeltvector3f_bufferoffset = 0;
8677                         rsurface.modelnormal3f_vertexbuffer = 0;
8678                         rsurface.modelnormal3f_bufferoffset = 0;
8679                 }
8680                 else if (wantnormals)
8681                 {
8682                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8683                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8684                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8685                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8686                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8687                         rsurface.modelsvector3f = NULL;
8688                         rsurface.modeltvector3f = NULL;
8689                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8690                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8691                         rsurface.modelvertexmesh = NULL;
8692                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8693                         rsurface.modelvertexmesh_bufferoffset = 0;
8694                         rsurface.modelvertex3f_vertexbuffer = NULL;
8695                         rsurface.modelvertex3f_bufferoffset = 0;
8696                         rsurface.modelvertex3f_vertexbuffer = 0;
8697                         rsurface.modelvertex3f_bufferoffset = 0;
8698                         rsurface.modelsvector3f_vertexbuffer = 0;
8699                         rsurface.modelsvector3f_bufferoffset = 0;
8700                         rsurface.modeltvector3f_vertexbuffer = 0;
8701                         rsurface.modeltvector3f_bufferoffset = 0;
8702                         rsurface.modelnormal3f_vertexbuffer = 0;
8703                         rsurface.modelnormal3f_bufferoffset = 0;
8704                 }
8705                 else
8706                 {
8707                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8708                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8709                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8710                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8711                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8712                         rsurface.modelsvector3f = NULL;
8713                         rsurface.modeltvector3f = NULL;
8714                         rsurface.modelnormal3f = NULL;
8715                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8716                         rsurface.modelvertexmesh = NULL;
8717                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8718                         rsurface.modelvertexmesh_bufferoffset = 0;
8719                         rsurface.modelvertex3f_vertexbuffer = NULL;
8720                         rsurface.modelvertex3f_bufferoffset = 0;
8721                         rsurface.modelvertex3f_vertexbuffer = 0;
8722                         rsurface.modelvertex3f_bufferoffset = 0;
8723                         rsurface.modelsvector3f_vertexbuffer = 0;
8724                         rsurface.modelsvector3f_bufferoffset = 0;
8725                         rsurface.modeltvector3f_vertexbuffer = 0;
8726                         rsurface.modeltvector3f_bufferoffset = 0;
8727                         rsurface.modelnormal3f_vertexbuffer = 0;
8728                         rsurface.modelnormal3f_bufferoffset = 0;
8729                 }
8730                 rsurface.modelgeneratedvertex = true;
8731         }
8732         else
8733         {
8734                 if (rsurface.entityskeletaltransform3x4)
8735                 {
8736                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8737                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8738                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8739                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8740                 }
8741                 else
8742                 {
8743                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8744                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8745                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8746                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8747                 }
8748                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8749                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8750                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8751                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8752                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8753                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8754                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8755                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8756                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8757                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8758                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8759                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8760                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8761                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8762                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8763                 rsurface.modelgeneratedvertex = false;
8764         }
8765         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8766         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8767         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8768         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8769         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8770         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8771         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8772         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8773         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8774         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8775         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8776         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8777         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8778         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8779         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8780         rsurface.modelelement3i = model->surfmesh.data_element3i;
8781         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8782         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8783         rsurface.modelelement3s = model->surfmesh.data_element3s;
8784         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8785         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8786         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8787         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8788         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8789         rsurface.modelsurfaces = model->data_surfaces;
8790         rsurface.batchgeneratedvertex = false;
8791         rsurface.batchfirstvertex = 0;
8792         rsurface.batchnumvertices = 0;
8793         rsurface.batchfirsttriangle = 0;
8794         rsurface.batchnumtriangles = 0;
8795         rsurface.batchvertex3f  = NULL;
8796         rsurface.batchvertex3f_vertexbuffer = NULL;
8797         rsurface.batchvertex3f_bufferoffset = 0;
8798         rsurface.batchsvector3f = NULL;
8799         rsurface.batchsvector3f_vertexbuffer = NULL;
8800         rsurface.batchsvector3f_bufferoffset = 0;
8801         rsurface.batchtvector3f = NULL;
8802         rsurface.batchtvector3f_vertexbuffer = NULL;
8803         rsurface.batchtvector3f_bufferoffset = 0;
8804         rsurface.batchnormal3f  = NULL;
8805         rsurface.batchnormal3f_vertexbuffer = NULL;
8806         rsurface.batchnormal3f_bufferoffset = 0;
8807         rsurface.batchlightmapcolor4f = NULL;
8808         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8809         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8810         rsurface.batchtexcoordtexture2f = NULL;
8811         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8812         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8813         rsurface.batchtexcoordlightmap2f = NULL;
8814         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8815         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8816         rsurface.batchskeletalindex4ub = NULL;
8817         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8818         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8819         rsurface.batchskeletalweight4ub = NULL;
8820         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8821         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8822         rsurface.batchvertexmesh = NULL;
8823         rsurface.batchvertexmesh_vertexbuffer = NULL;
8824         rsurface.batchvertexmesh_bufferoffset = 0;
8825         rsurface.batchelement3i = NULL;
8826         rsurface.batchelement3i_indexbuffer = NULL;
8827         rsurface.batchelement3i_bufferoffset = 0;
8828         rsurface.batchelement3s = NULL;
8829         rsurface.batchelement3s_indexbuffer = NULL;
8830         rsurface.batchelement3s_bufferoffset = 0;
8831         rsurface.passcolor4f = NULL;
8832         rsurface.passcolor4f_vertexbuffer = NULL;
8833         rsurface.passcolor4f_bufferoffset = 0;
8834         rsurface.forcecurrenttextureupdate = false;
8835 }
8836
8837 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)
8838 {
8839         rsurface.entity = r_refdef.scene.worldentity;
8840         rsurface.skeleton = NULL;
8841         rsurface.ent_skinnum = 0;
8842         rsurface.ent_qwskin = -1;
8843         rsurface.ent_flags = entflags;
8844         rsurface.shadertime = r_refdef.scene.time - shadertime;
8845         rsurface.modelnumvertices = numvertices;
8846         rsurface.modelnumtriangles = numtriangles;
8847         rsurface.matrix = *matrix;
8848         rsurface.inversematrix = *inversematrix;
8849         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8850         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8851         R_EntityMatrix(&rsurface.matrix);
8852         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8853         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8854         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8855         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8856         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8857         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8858         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8859         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8860         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8861         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8862         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8863         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8864         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);
8865         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8866         rsurface.frameblend[0].lerp = 1;
8867         rsurface.ent_alttextures = false;
8868         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8869         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8870         rsurface.entityskeletaltransform3x4 = NULL;
8871         rsurface.entityskeletaltransform3x4buffer = NULL;
8872         rsurface.entityskeletaltransform3x4offset = 0;
8873         rsurface.entityskeletaltransform3x4size = 0;
8874         rsurface.entityskeletalnumtransforms = 0;
8875         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8876         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8877         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8878         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8879         if (wanttangents)
8880         {
8881                 rsurface.modelvertex3f = (float *)vertex3f;
8882                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8883                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8884                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8885         }
8886         else if (wantnormals)
8887         {
8888                 rsurface.modelvertex3f = (float *)vertex3f;
8889                 rsurface.modelsvector3f = NULL;
8890                 rsurface.modeltvector3f = NULL;
8891                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8892         }
8893         else
8894         {
8895                 rsurface.modelvertex3f = (float *)vertex3f;
8896                 rsurface.modelsvector3f = NULL;
8897                 rsurface.modeltvector3f = NULL;
8898                 rsurface.modelnormal3f = NULL;
8899         }
8900         rsurface.modelvertexmesh = NULL;
8901         rsurface.modelvertexmesh_vertexbuffer = NULL;
8902         rsurface.modelvertexmesh_bufferoffset = 0;
8903         rsurface.modelvertex3f_vertexbuffer = 0;
8904         rsurface.modelvertex3f_bufferoffset = 0;
8905         rsurface.modelsvector3f_vertexbuffer = 0;
8906         rsurface.modelsvector3f_bufferoffset = 0;
8907         rsurface.modeltvector3f_vertexbuffer = 0;
8908         rsurface.modeltvector3f_bufferoffset = 0;
8909         rsurface.modelnormal3f_vertexbuffer = 0;
8910         rsurface.modelnormal3f_bufferoffset = 0;
8911         rsurface.modelgeneratedvertex = true;
8912         rsurface.modellightmapcolor4f  = (float *)color4f;
8913         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8914         rsurface.modellightmapcolor4f_bufferoffset = 0;
8915         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8916         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8917         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8918         rsurface.modeltexcoordlightmap2f  = NULL;
8919         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8920         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8921         rsurface.modelskeletalindex4ub = NULL;
8922         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8923         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8924         rsurface.modelskeletalweight4ub = NULL;
8925         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8926         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8927         rsurface.modelelement3i = (int *)element3i;
8928         rsurface.modelelement3i_indexbuffer = NULL;
8929         rsurface.modelelement3i_bufferoffset = 0;
8930         rsurface.modelelement3s = (unsigned short *)element3s;
8931         rsurface.modelelement3s_indexbuffer = NULL;
8932         rsurface.modelelement3s_bufferoffset = 0;
8933         rsurface.modellightmapoffsets = NULL;
8934         rsurface.modelsurfaces = NULL;
8935         rsurface.batchgeneratedvertex = false;
8936         rsurface.batchfirstvertex = 0;
8937         rsurface.batchnumvertices = 0;
8938         rsurface.batchfirsttriangle = 0;
8939         rsurface.batchnumtriangles = 0;
8940         rsurface.batchvertex3f  = NULL;
8941         rsurface.batchvertex3f_vertexbuffer = NULL;
8942         rsurface.batchvertex3f_bufferoffset = 0;
8943         rsurface.batchsvector3f = NULL;
8944         rsurface.batchsvector3f_vertexbuffer = NULL;
8945         rsurface.batchsvector3f_bufferoffset = 0;
8946         rsurface.batchtvector3f = NULL;
8947         rsurface.batchtvector3f_vertexbuffer = NULL;
8948         rsurface.batchtvector3f_bufferoffset = 0;
8949         rsurface.batchnormal3f  = NULL;
8950         rsurface.batchnormal3f_vertexbuffer = NULL;
8951         rsurface.batchnormal3f_bufferoffset = 0;
8952         rsurface.batchlightmapcolor4f = NULL;
8953         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8954         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8955         rsurface.batchtexcoordtexture2f = NULL;
8956         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8957         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8958         rsurface.batchtexcoordlightmap2f = NULL;
8959         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8960         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8961         rsurface.batchskeletalindex4ub = NULL;
8962         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8963         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8964         rsurface.batchskeletalweight4ub = NULL;
8965         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8966         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8967         rsurface.batchvertexmesh = NULL;
8968         rsurface.batchvertexmesh_vertexbuffer = NULL;
8969         rsurface.batchvertexmesh_bufferoffset = 0;
8970         rsurface.batchelement3i = NULL;
8971         rsurface.batchelement3i_indexbuffer = NULL;
8972         rsurface.batchelement3i_bufferoffset = 0;
8973         rsurface.batchelement3s = NULL;
8974         rsurface.batchelement3s_indexbuffer = NULL;
8975         rsurface.batchelement3s_bufferoffset = 0;
8976         rsurface.passcolor4f = NULL;
8977         rsurface.passcolor4f_vertexbuffer = NULL;
8978         rsurface.passcolor4f_bufferoffset = 0;
8979         rsurface.forcecurrenttextureupdate = true;
8980
8981         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8982         {
8983                 if ((wantnormals || wanttangents) && !normal3f)
8984                 {
8985                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8986                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8987                 }
8988                 if (wanttangents && !svector3f)
8989                 {
8990                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8991                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8992                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8993                 }
8994         }
8995 }
8996
8997 float RSurf_FogPoint(const float *v)
8998 {
8999         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9000         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9001         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9002         float FogHeightFade = r_refdef.fogheightfade;
9003         float fogfrac;
9004         unsigned int fogmasktableindex;
9005         if (r_refdef.fogplaneviewabove)
9006                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9007         else
9008                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9009         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9010         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9011 }
9012
9013 float RSurf_FogVertex(const float *v)
9014 {
9015         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9016         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9017         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9018         float FogHeightFade = rsurface.fogheightfade;
9019         float fogfrac;
9020         unsigned int fogmasktableindex;
9021         if (r_refdef.fogplaneviewabove)
9022                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9023         else
9024                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9025         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9026         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9027 }
9028
9029 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9030 {
9031         int i;
9032         for (i = 0;i < numelements;i++)
9033                 outelement3i[i] = inelement3i[i] + adjust;
9034 }
9035
9036 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9037 extern cvar_t gl_vbo;
9038 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9039 {
9040         int deformindex;
9041         int firsttriangle;
9042         int numtriangles;
9043         int firstvertex;
9044         int endvertex;
9045         int numvertices;
9046         int surfacefirsttriangle;
9047         int surfacenumtriangles;
9048         int surfacefirstvertex;
9049         int surfaceendvertex;
9050         int surfacenumvertices;
9051         int batchnumsurfaces = texturenumsurfaces;
9052         int batchnumvertices;
9053         int batchnumtriangles;
9054         int needsupdate;
9055         int i, j;
9056         qboolean gaps;
9057         qboolean dynamicvertex;
9058         float amplitude;
9059         float animpos;
9060         float scale;
9061         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9062         float waveparms[4];
9063         unsigned char *ub;
9064         q3shaderinfo_deform_t *deform;
9065         const msurface_t *surface, *firstsurface;
9066         r_vertexmesh_t *vertexmesh;
9067         if (!texturenumsurfaces)
9068                 return;
9069         // find vertex range of this surface batch
9070         gaps = false;
9071         firstsurface = texturesurfacelist[0];
9072         firsttriangle = firstsurface->num_firsttriangle;
9073         batchnumvertices = 0;
9074         batchnumtriangles = 0;
9075         firstvertex = endvertex = firstsurface->num_firstvertex;
9076         for (i = 0;i < texturenumsurfaces;i++)
9077         {
9078                 surface = texturesurfacelist[i];
9079                 if (surface != firstsurface + i)
9080                         gaps = true;
9081                 surfacefirstvertex = surface->num_firstvertex;
9082                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9083                 surfacenumvertices = surface->num_vertices;
9084                 surfacenumtriangles = surface->num_triangles;
9085                 if (firstvertex > surfacefirstvertex)
9086                         firstvertex = surfacefirstvertex;
9087                 if (endvertex < surfaceendvertex)
9088                         endvertex = surfaceendvertex;
9089                 batchnumvertices += surfacenumvertices;
9090                 batchnumtriangles += surfacenumtriangles;
9091         }
9092
9093         r_refdef.stats[r_stat_batch_batches]++;
9094         if (gaps)
9095                 r_refdef.stats[r_stat_batch_withgaps]++;
9096         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9097         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9098         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9099
9100         // we now know the vertex range used, and if there are any gaps in it
9101         rsurface.batchfirstvertex = firstvertex;
9102         rsurface.batchnumvertices = endvertex - firstvertex;
9103         rsurface.batchfirsttriangle = firsttriangle;
9104         rsurface.batchnumtriangles = batchnumtriangles;
9105
9106         // this variable holds flags for which properties have been updated that
9107         // may require regenerating vertexmesh array...
9108         needsupdate = 0;
9109
9110         // check if any dynamic vertex processing must occur
9111         dynamicvertex = false;
9112
9113         // a cvar to force the dynamic vertex path to be taken, for debugging
9114         if (r_batch_debugdynamicvertexpath.integer)
9115         {
9116                 if (!dynamicvertex)
9117                 {
9118                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9119                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9120                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9121                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9122                 }
9123                 dynamicvertex = true;
9124         }
9125
9126         // if there is a chance of animated vertex colors, it's a dynamic batch
9127         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9128         {
9129                 if (!dynamicvertex)
9130                 {
9131                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9132                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9133                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9134                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9135                 }
9136                 dynamicvertex = true;
9137                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9138         }
9139
9140         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9141         {
9142                 switch (deform->deform)
9143                 {
9144                 default:
9145                 case Q3DEFORM_PROJECTIONSHADOW:
9146                 case Q3DEFORM_TEXT0:
9147                 case Q3DEFORM_TEXT1:
9148                 case Q3DEFORM_TEXT2:
9149                 case Q3DEFORM_TEXT3:
9150                 case Q3DEFORM_TEXT4:
9151                 case Q3DEFORM_TEXT5:
9152                 case Q3DEFORM_TEXT6:
9153                 case Q3DEFORM_TEXT7:
9154                 case Q3DEFORM_NONE:
9155                         break;
9156                 case Q3DEFORM_AUTOSPRITE:
9157                         if (!dynamicvertex)
9158                         {
9159                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9160                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9161                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9162                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9163                         }
9164                         dynamicvertex = true;
9165                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9166                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9167                         break;
9168                 case Q3DEFORM_AUTOSPRITE2:
9169                         if (!dynamicvertex)
9170                         {
9171                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9172                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9173                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9174                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9175                         }
9176                         dynamicvertex = true;
9177                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9178                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9179                         break;
9180                 case Q3DEFORM_NORMAL:
9181                         if (!dynamicvertex)
9182                         {
9183                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9184                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9185                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9186                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9187                         }
9188                         dynamicvertex = true;
9189                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9190                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9191                         break;
9192                 case Q3DEFORM_WAVE:
9193                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9194                                 break; // if wavefunc is a nop, ignore this transform
9195                         if (!dynamicvertex)
9196                         {
9197                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9198                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9199                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9200                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9201                         }
9202                         dynamicvertex = true;
9203                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9204                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9205                         break;
9206                 case Q3DEFORM_BULGE:
9207                         if (!dynamicvertex)
9208                         {
9209                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9210                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9211                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9212                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9213                         }
9214                         dynamicvertex = true;
9215                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9216                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9217                         break;
9218                 case Q3DEFORM_MOVE:
9219                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9220                                 break; // if wavefunc is a nop, ignore this transform
9221                         if (!dynamicvertex)
9222                         {
9223                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9224                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9225                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9226                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9227                         }
9228                         dynamicvertex = true;
9229                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9230                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9231                         break;
9232                 }
9233         }
9234         switch(rsurface.texture->tcgen.tcgen)
9235         {
9236         default:
9237         case Q3TCGEN_TEXTURE:
9238                 break;
9239         case Q3TCGEN_LIGHTMAP:
9240                 if (!dynamicvertex)
9241                 {
9242                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9243                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9244                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9245                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9246                 }
9247                 dynamicvertex = true;
9248                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9249                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9250                 break;
9251         case Q3TCGEN_VECTOR:
9252                 if (!dynamicvertex)
9253                 {
9254                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9255                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9256                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9257                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9258                 }
9259                 dynamicvertex = true;
9260                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9261                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9262                 break;
9263         case Q3TCGEN_ENVIRONMENT:
9264                 if (!dynamicvertex)
9265                 {
9266                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9267                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9268                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9269                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9270                 }
9271                 dynamicvertex = true;
9272                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9273                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9274                 break;
9275         }
9276         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9277         {
9278                 if (!dynamicvertex)
9279                 {
9280                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9281                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9282                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9283                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9284                 }
9285                 dynamicvertex = true;
9286                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9287                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9288         }
9289
9290         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9291         {
9292                 if (!dynamicvertex)
9293                 {
9294                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9295                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9296                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9297                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9298                 }
9299                 dynamicvertex = true;
9300                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9301         }
9302
9303         // when the model data has no vertex buffer (dynamic mesh), we need to
9304         // eliminate gaps
9305         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9306                 batchneed |= BATCHNEED_NOGAPS;
9307
9308         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9309         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9310         // we ensure this by treating the vertex batch as dynamic...
9311         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9312         {
9313                 if (!dynamicvertex)
9314                 {
9315                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9316                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9317                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9318                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9319                 }
9320                 dynamicvertex = true;
9321         }
9322
9323         if (dynamicvertex)
9324         {
9325                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9326                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9327                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9328                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9329                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9330                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9331                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9332                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9333         }
9334
9335         // if needsupdate, we have to do a dynamic vertex batch for sure
9336         if (needsupdate & batchneed)
9337         {
9338                 if (!dynamicvertex)
9339                 {
9340                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9341                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9342                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9343                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9344                 }
9345                 dynamicvertex = true;
9346         }
9347
9348         // see if we need to build vertexmesh from arrays
9349         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9350         {
9351                 if (!dynamicvertex)
9352                 {
9353                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9354                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9355                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9356                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9357                 }
9358                 dynamicvertex = true;
9359         }
9360
9361         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9362         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9363                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9364
9365         rsurface.batchvertex3f = rsurface.modelvertex3f;
9366         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9367         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9368         rsurface.batchsvector3f = rsurface.modelsvector3f;
9369         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9370         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9371         rsurface.batchtvector3f = rsurface.modeltvector3f;
9372         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9373         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9374         rsurface.batchnormal3f = rsurface.modelnormal3f;
9375         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9376         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9377         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9378         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9379         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9380         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9381         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9382         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9383         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9384         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9385         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9386         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9387         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9388         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9389         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9390         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9391         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9392         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9393         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9394         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9395         rsurface.batchelement3i = rsurface.modelelement3i;
9396         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9397         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9398         rsurface.batchelement3s = rsurface.modelelement3s;
9399         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9400         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9401         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9402         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9403         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9404         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9405         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9406
9407         // if any dynamic vertex processing has to occur in software, we copy the
9408         // entire surface list together before processing to rebase the vertices
9409         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9410         //
9411         // if any gaps exist and we do not have a static vertex buffer, we have to
9412         // copy the surface list together to avoid wasting upload bandwidth on the
9413         // vertices in the gaps.
9414         //
9415         // if gaps exist and we have a static vertex buffer, we can choose whether
9416         // to combine the index buffer ranges into one dynamic index buffer or
9417         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9418         //
9419         // in many cases the batch is reduced to one draw call.
9420
9421         rsurface.batchmultidraw = false;
9422         rsurface.batchmultidrawnumsurfaces = 0;
9423         rsurface.batchmultidrawsurfacelist = NULL;
9424
9425         if (!dynamicvertex)
9426         {
9427                 // static vertex data, just set pointers...
9428                 rsurface.batchgeneratedvertex = false;
9429                 // if there are gaps, we want to build a combined index buffer,
9430                 // otherwise use the original static buffer with an appropriate offset
9431                 if (gaps)
9432                 {
9433                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9434                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9435                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9436                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9437                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9438                         {
9439                                 rsurface.batchmultidraw = true;
9440                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9441                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9442                                 return;
9443                         }
9444                         // build a new triangle elements array for this batch
9445                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9446                         rsurface.batchfirsttriangle = 0;
9447                         numtriangles = 0;
9448                         for (i = 0;i < texturenumsurfaces;i++)
9449                         {
9450                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9451                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9452                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9453                                 numtriangles += surfacenumtriangles;
9454                         }
9455                         rsurface.batchelement3i_indexbuffer = NULL;
9456                         rsurface.batchelement3i_bufferoffset = 0;
9457                         rsurface.batchelement3s = NULL;
9458                         rsurface.batchelement3s_indexbuffer = NULL;
9459                         rsurface.batchelement3s_bufferoffset = 0;
9460                         if (endvertex <= 65536)
9461                         {
9462                                 // make a 16bit (unsigned short) index array if possible
9463                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9464                                 for (i = 0;i < numtriangles*3;i++)
9465                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9466                         }
9467                         // upload buffer data for the copytriangles batch
9468                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9469                         {
9470                                 if (rsurface.batchelement3s)
9471                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9472                                 else if (rsurface.batchelement3i)
9473                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9474                         }
9475                 }
9476                 else
9477                 {
9478                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9479                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9480                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9481                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9482                 }
9483                 return;
9484         }
9485
9486         // something needs software processing, do it for real...
9487         // we only directly handle separate array data in this case and then
9488         // generate interleaved data if needed...
9489         rsurface.batchgeneratedvertex = true;
9490         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9491         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9492         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9493         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9494
9495         // now copy the vertex data into a combined array and make an index array
9496         // (this is what Quake3 does all the time)
9497         // we also apply any skeletal animation here that would have been done in
9498         // the vertex shader, because most of the dynamic vertex animation cases
9499         // need actual vertex positions and normals
9500         //if (dynamicvertex)
9501         {
9502                 rsurface.batchvertexmesh = NULL;
9503                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9504                 rsurface.batchvertexmesh_bufferoffset = 0;
9505                 rsurface.batchvertex3f = NULL;
9506                 rsurface.batchvertex3f_vertexbuffer = NULL;
9507                 rsurface.batchvertex3f_bufferoffset = 0;
9508                 rsurface.batchsvector3f = NULL;
9509                 rsurface.batchsvector3f_vertexbuffer = NULL;
9510                 rsurface.batchsvector3f_bufferoffset = 0;
9511                 rsurface.batchtvector3f = NULL;
9512                 rsurface.batchtvector3f_vertexbuffer = NULL;
9513                 rsurface.batchtvector3f_bufferoffset = 0;
9514                 rsurface.batchnormal3f = NULL;
9515                 rsurface.batchnormal3f_vertexbuffer = NULL;
9516                 rsurface.batchnormal3f_bufferoffset = 0;
9517                 rsurface.batchlightmapcolor4f = NULL;
9518                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9519                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9520                 rsurface.batchtexcoordtexture2f = NULL;
9521                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9522                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9523                 rsurface.batchtexcoordlightmap2f = NULL;
9524                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9525                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9526                 rsurface.batchskeletalindex4ub = NULL;
9527                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9528                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9529                 rsurface.batchskeletalweight4ub = NULL;
9530                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9531                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9532                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9533                 rsurface.batchelement3i_indexbuffer = NULL;
9534                 rsurface.batchelement3i_bufferoffset = 0;
9535                 rsurface.batchelement3s = NULL;
9536                 rsurface.batchelement3s_indexbuffer = NULL;
9537                 rsurface.batchelement3s_bufferoffset = 0;
9538                 rsurface.batchskeletaltransform3x4buffer = NULL;
9539                 rsurface.batchskeletaltransform3x4offset = 0;
9540                 rsurface.batchskeletaltransform3x4size = 0;
9541                 // we'll only be setting up certain arrays as needed
9542                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9543                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9544                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9545                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9546                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9547                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9548                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9549                 {
9550                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9551                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9552                 }
9553                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9554                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9555                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9556                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9557                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9558                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9559                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9560                 {
9561                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9562                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9563                 }
9564                 numvertices = 0;
9565                 numtriangles = 0;
9566                 for (i = 0;i < texturenumsurfaces;i++)
9567                 {
9568                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9569                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9570                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9571                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9572                         // copy only the data requested
9573                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9574                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9575                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9576                         {
9577                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9578                                 {
9579                                         if (rsurface.batchvertex3f)
9580                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9581                                         else
9582                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9583                                 }
9584                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9585                                 {
9586                                         if (rsurface.modelnormal3f)
9587                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9588                                         else
9589                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9590                                 }
9591                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9592                                 {
9593                                         if (rsurface.modelsvector3f)
9594                                         {
9595                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9596                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9597                                         }
9598                                         else
9599                                         {
9600                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9601                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9602                                         }
9603                                 }
9604                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9605                                 {
9606                                         if (rsurface.modellightmapcolor4f)
9607                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9608                                         else
9609                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9610                                 }
9611                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9612                                 {
9613                                         if (rsurface.modeltexcoordtexture2f)
9614                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9615                                         else
9616                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9617                                 }
9618                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9619                                 {
9620                                         if (rsurface.modeltexcoordlightmap2f)
9621                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9622                                         else
9623                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9624                                 }
9625                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9626                                 {
9627                                         if (rsurface.modelskeletalindex4ub)
9628                                         {
9629                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9630                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9631                                         }
9632                                         else
9633                                         {
9634                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9635                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9636                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9637                                                 for (j = 0;j < surfacenumvertices;j++)
9638                                                         ub[j*4] = 255;
9639                                         }
9640                                 }
9641                         }
9642                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9643                         numvertices += surfacenumvertices;
9644                         numtriangles += surfacenumtriangles;
9645                 }
9646
9647                 // generate a 16bit index array as well if possible
9648                 // (in general, dynamic batches fit)
9649                 if (numvertices <= 65536)
9650                 {
9651                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9652                         for (i = 0;i < numtriangles*3;i++)
9653                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9654                 }
9655
9656                 // since we've copied everything, the batch now starts at 0
9657                 rsurface.batchfirstvertex = 0;
9658                 rsurface.batchnumvertices = batchnumvertices;
9659                 rsurface.batchfirsttriangle = 0;
9660                 rsurface.batchnumtriangles = batchnumtriangles;
9661         }
9662
9663         // apply skeletal animation that would have been done in the vertex shader
9664         if (rsurface.batchskeletaltransform3x4)
9665         {
9666                 const unsigned char *si;
9667                 const unsigned char *sw;
9668                 const float *t[4];
9669                 const float *b = rsurface.batchskeletaltransform3x4;
9670                 float *vp, *vs, *vt, *vn;
9671                 float w[4];
9672                 float m[3][4], n[3][4];
9673                 float tp[3], ts[3], tt[3], tn[3];
9674                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9675                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9676                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9677                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9678                 si = rsurface.batchskeletalindex4ub;
9679                 sw = rsurface.batchskeletalweight4ub;
9680                 vp = rsurface.batchvertex3f;
9681                 vs = rsurface.batchsvector3f;
9682                 vt = rsurface.batchtvector3f;
9683                 vn = rsurface.batchnormal3f;
9684                 memset(m[0], 0, sizeof(m));
9685                 memset(n[0], 0, sizeof(n));
9686                 for (i = 0;i < batchnumvertices;i++)
9687                 {
9688                         t[0] = b + si[0]*12;
9689                         if (sw[0] == 255)
9690                         {
9691                                 // common case - only one matrix
9692                                 m[0][0] = t[0][ 0];
9693                                 m[0][1] = t[0][ 1];
9694                                 m[0][2] = t[0][ 2];
9695                                 m[0][3] = t[0][ 3];
9696                                 m[1][0] = t[0][ 4];
9697                                 m[1][1] = t[0][ 5];
9698                                 m[1][2] = t[0][ 6];
9699                                 m[1][3] = t[0][ 7];
9700                                 m[2][0] = t[0][ 8];
9701                                 m[2][1] = t[0][ 9];
9702                                 m[2][2] = t[0][10];
9703                                 m[2][3] = t[0][11];
9704                         }
9705                         else if (sw[2] + sw[3])
9706                         {
9707                                 // blend 4 matrices
9708                                 t[1] = b + si[1]*12;
9709                                 t[2] = b + si[2]*12;
9710                                 t[3] = b + si[3]*12;
9711                                 w[0] = sw[0] * (1.0f / 255.0f);
9712                                 w[1] = sw[1] * (1.0f / 255.0f);
9713                                 w[2] = sw[2] * (1.0f / 255.0f);
9714                                 w[3] = sw[3] * (1.0f / 255.0f);
9715                                 // blend the matrices
9716                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9717                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9718                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9719                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9720                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9721                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9722                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9723                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9724                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9725                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9726                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9727                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9728                         }
9729                         else
9730                         {
9731                                 // blend 2 matrices
9732                                 t[1] = b + si[1]*12;
9733                                 w[0] = sw[0] * (1.0f / 255.0f);
9734                                 w[1] = sw[1] * (1.0f / 255.0f);
9735                                 // blend the matrices
9736                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9737                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9738                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9739                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9740                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9741                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9742                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9743                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9744                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9745                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9746                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9747                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9748                         }
9749                         si += 4;
9750                         sw += 4;
9751                         // modify the vertex
9752                         VectorCopy(vp, tp);
9753                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9754                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9755                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9756                         vp += 3;
9757                         if (vn)
9758                         {
9759                                 // the normal transformation matrix is a set of cross products...
9760                                 CrossProduct(m[1], m[2], n[0]);
9761                                 CrossProduct(m[2], m[0], n[1]);
9762                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9763                                 VectorCopy(vn, tn);
9764                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9765                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9766                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9767                                 VectorNormalize(vn);
9768                                 vn += 3;
9769                                 if (vs)
9770                                 {
9771                                         VectorCopy(vs, ts);
9772                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9773                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9774                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9775                                         VectorNormalize(vs);
9776                                         vs += 3;
9777                                         VectorCopy(vt, tt);
9778                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9779                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9780                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9781                                         VectorNormalize(vt);
9782                                         vt += 3;
9783                                 }
9784                         }
9785                 }
9786                 rsurface.batchskeletaltransform3x4 = NULL;
9787                 rsurface.batchskeletalnumtransforms = 0;
9788         }
9789
9790         // q1bsp surfaces rendered in vertex color mode have to have colors
9791         // calculated based on lightstyles
9792         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9793         {
9794                 // generate color arrays for the surfaces in this list
9795                 int c[4];
9796                 int scale;
9797                 int size3;
9798                 const int *offsets;
9799                 const unsigned char *lm;
9800                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9801                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9802                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9803                 numvertices = 0;
9804                 for (i = 0;i < texturenumsurfaces;i++)
9805                 {
9806                         surface = texturesurfacelist[i];
9807                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9808                         surfacenumvertices = surface->num_vertices;
9809                         if (surface->lightmapinfo->samples)
9810                         {
9811                                 for (j = 0;j < surfacenumvertices;j++)
9812                                 {
9813                                         lm = surface->lightmapinfo->samples + offsets[j];
9814                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9815                                         VectorScale(lm, scale, c);
9816                                         if (surface->lightmapinfo->styles[1] != 255)
9817                                         {
9818                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9819                                                 lm += size3;
9820                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9821                                                 VectorMA(c, scale, lm, c);
9822                                                 if (surface->lightmapinfo->styles[2] != 255)
9823                                                 {
9824                                                         lm += size3;
9825                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9826                                                         VectorMA(c, scale, lm, c);
9827                                                         if (surface->lightmapinfo->styles[3] != 255)
9828                                                         {
9829                                                                 lm += size3;
9830                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9831                                                                 VectorMA(c, scale, lm, c);
9832                                                         }
9833                                                 }
9834                                         }
9835                                         c[0] >>= 7;
9836                                         c[1] >>= 7;
9837                                         c[2] >>= 7;
9838                                         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);
9839                                         numvertices++;
9840                                 }
9841                         }
9842                         else
9843                         {
9844                                 for (j = 0;j < surfacenumvertices;j++)
9845                                 {
9846                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9847                                         numvertices++;
9848                                 }
9849                         }
9850                 }
9851         }
9852
9853         // if vertices are deformed (sprite flares and things in maps, possibly
9854         // water waves, bulges and other deformations), modify the copied vertices
9855         // in place
9856         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9857         {
9858                 switch (deform->deform)
9859                 {
9860                 default:
9861                 case Q3DEFORM_PROJECTIONSHADOW:
9862                 case Q3DEFORM_TEXT0:
9863                 case Q3DEFORM_TEXT1:
9864                 case Q3DEFORM_TEXT2:
9865                 case Q3DEFORM_TEXT3:
9866                 case Q3DEFORM_TEXT4:
9867                 case Q3DEFORM_TEXT5:
9868                 case Q3DEFORM_TEXT6:
9869                 case Q3DEFORM_TEXT7:
9870                 case Q3DEFORM_NONE:
9871                         break;
9872                 case Q3DEFORM_AUTOSPRITE:
9873                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9874                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9875                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9876                         VectorNormalize(newforward);
9877                         VectorNormalize(newright);
9878                         VectorNormalize(newup);
9879 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9880 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9881 //                      rsurface.batchvertex3f_bufferoffset = 0;
9882 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9883 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9884 //                      rsurface.batchsvector3f_bufferoffset = 0;
9885 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9886 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9887 //                      rsurface.batchtvector3f_bufferoffset = 0;
9888 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9889 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9890 //                      rsurface.batchnormal3f_bufferoffset = 0;
9891                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9892                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9893                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9894                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9895                                 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);
9896                         // a single autosprite surface can contain multiple sprites...
9897                         for (j = 0;j < batchnumvertices - 3;j += 4)
9898                         {
9899                                 VectorClear(center);
9900                                 for (i = 0;i < 4;i++)
9901                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9902                                 VectorScale(center, 0.25f, center);
9903                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9904                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9905                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9906                                 for (i = 0;i < 4;i++)
9907                                 {
9908                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9909                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9910                                 }
9911                         }
9912                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9913                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9914                         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);
9915                         break;
9916                 case Q3DEFORM_AUTOSPRITE2:
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                         {
9927                                 const float *v1, *v2;
9928                                 vec3_t start, end;
9929                                 float f, l;
9930                                 struct
9931                                 {
9932                                         float length2;
9933                                         const float *v1;
9934                                         const float *v2;
9935                                 }
9936                                 shortest[2];
9937                                 memset(shortest, 0, sizeof(shortest));
9938                                 // a single autosprite surface can contain multiple sprites...
9939                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9940                                 {
9941                                         VectorClear(center);
9942                                         for (i = 0;i < 4;i++)
9943                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9944                                         VectorScale(center, 0.25f, center);
9945                                         // find the two shortest edges, then use them to define the
9946                                         // axis vectors for rotating around the central axis
9947                                         for (i = 0;i < 6;i++)
9948                                         {
9949                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9950                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9951                                                 l = VectorDistance2(v1, v2);
9952                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9953                                                 if (v1[2] != v2[2])
9954                                                         l += (1.0f / 1024.0f);
9955                                                 if (shortest[0].length2 > l || i == 0)
9956                                                 {
9957                                                         shortest[1] = shortest[0];
9958                                                         shortest[0].length2 = l;
9959                                                         shortest[0].v1 = v1;
9960                                                         shortest[0].v2 = v2;
9961                                                 }
9962                                                 else if (shortest[1].length2 > l || i == 1)
9963                                                 {
9964                                                         shortest[1].length2 = l;
9965                                                         shortest[1].v1 = v1;
9966                                                         shortest[1].v2 = v2;
9967                                                 }
9968                                         }
9969                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9970                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9971                                         // this calculates the right vector from the shortest edge
9972                                         // and the up vector from the edge midpoints
9973                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9974                                         VectorNormalize(right);
9975                                         VectorSubtract(end, start, up);
9976                                         VectorNormalize(up);
9977                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9978                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9979                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9980                                         VectorNegate(forward, forward);
9981                                         VectorReflect(forward, 0, up, forward);
9982                                         VectorNormalize(forward);
9983                                         CrossProduct(up, forward, newright);
9984                                         VectorNormalize(newright);
9985                                         // rotate the quad around the up axis vector, this is made
9986                                         // especially easy by the fact we know the quad is flat,
9987                                         // so we only have to subtract the center position and
9988                                         // measure distance along the right vector, and then
9989                                         // multiply that by the newright vector and add back the
9990                                         // center position
9991                                         // we also need to subtract the old position to undo the
9992                                         // displacement from the center, which we do with a
9993                                         // DotProduct, the subtraction/addition of center is also
9994                                         // optimized into DotProducts here
9995                                         l = DotProduct(right, center);
9996                                         for (i = 0;i < 4;i++)
9997                                         {
9998                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9999                                                 f = DotProduct(right, v1) - l;
10000                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10001                                         }
10002                                 }
10003                         }
10004                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10005                         {
10006 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10007 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10008 //                              rsurface.batchnormal3f_bufferoffset = 0;
10009                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10010                         }
10011                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10012                         {
10013 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10014 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10015 //                              rsurface.batchsvector3f_bufferoffset = 0;
10016 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10017 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10018 //                              rsurface.batchtvector3f_bufferoffset = 0;
10019                                 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);
10020                         }
10021                         break;
10022                 case Q3DEFORM_NORMAL:
10023                         // deform the normals to make reflections wavey
10024                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10025                         rsurface.batchnormal3f_vertexbuffer = NULL;
10026                         rsurface.batchnormal3f_bufferoffset = 0;
10027                         for (j = 0;j < batchnumvertices;j++)
10028                         {
10029                                 float vertex[3];
10030                                 float *normal = rsurface.batchnormal3f + 3*j;
10031                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10032                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10033                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10034                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10035                                 VectorNormalize(normal);
10036                         }
10037                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10038                         {
10039 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10040 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10041 //                              rsurface.batchsvector3f_bufferoffset = 0;
10042 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10043 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10044 //                              rsurface.batchtvector3f_bufferoffset = 0;
10045                                 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);
10046                         }
10047                         break;
10048                 case Q3DEFORM_WAVE:
10049                         // deform vertex array to make wavey water and flags and such
10050                         waveparms[0] = deform->waveparms[0];
10051                         waveparms[1] = deform->waveparms[1];
10052                         waveparms[2] = deform->waveparms[2];
10053                         waveparms[3] = deform->waveparms[3];
10054                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10055                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10056                         // this is how a divisor of vertex influence on deformation
10057                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10058                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10059 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10060 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10061 //                      rsurface.batchvertex3f_bufferoffset = 0;
10062 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10063 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10064 //                      rsurface.batchnormal3f_bufferoffset = 0;
10065                         for (j = 0;j < batchnumvertices;j++)
10066                         {
10067                                 // if the wavefunc depends on time, evaluate it per-vertex
10068                                 if (waveparms[3])
10069                                 {
10070                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10071                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10072                                 }
10073                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10074                         }
10075                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10076                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10077                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10078                         {
10079 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10080 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10081 //                              rsurface.batchsvector3f_bufferoffset = 0;
10082 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10083 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10084 //                              rsurface.batchtvector3f_bufferoffset = 0;
10085                                 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);
10086                         }
10087                         break;
10088                 case Q3DEFORM_BULGE:
10089                         // deform vertex array to make the surface have moving bulges
10090 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10091 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10092 //                      rsurface.batchvertex3f_bufferoffset = 0;
10093 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10094 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10095 //                      rsurface.batchnormal3f_bufferoffset = 0;
10096                         for (j = 0;j < batchnumvertices;j++)
10097                         {
10098                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10099                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10100                         }
10101                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10102                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10103                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10104                         {
10105 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10106 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10107 //                              rsurface.batchsvector3f_bufferoffset = 0;
10108 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10109 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10110 //                              rsurface.batchtvector3f_bufferoffset = 0;
10111                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
10112                         }
10113                         break;
10114                 case Q3DEFORM_MOVE:
10115                         // deform vertex array
10116                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10117                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10118                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10119                         VectorScale(deform->parms, scale, waveparms);
10120 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10121 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10122 //                      rsurface.batchvertex3f_bufferoffset = 0;
10123                         for (j = 0;j < batchnumvertices;j++)
10124                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10125                         break;
10126                 }
10127         }
10128
10129         if (rsurface.batchtexcoordtexture2f)
10130         {
10131         // generate texcoords based on the chosen texcoord source
10132                 switch(rsurface.texture->tcgen.tcgen)
10133                 {
10134                 default:
10135                 case Q3TCGEN_TEXTURE:
10136                         break;
10137                 case Q3TCGEN_LIGHTMAP:
10138         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10139         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10140         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10141                         if (rsurface.batchtexcoordlightmap2f)
10142                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10143                         break;
10144                 case Q3TCGEN_VECTOR:
10145         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10146         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10147         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10148                         for (j = 0;j < batchnumvertices;j++)
10149                         {
10150                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10151                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10152                         }
10153                         break;
10154                 case Q3TCGEN_ENVIRONMENT:
10155                         // make environment reflections using a spheremap
10156                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10157                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10158                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10159                         for (j = 0;j < batchnumvertices;j++)
10160                         {
10161                                 // identical to Q3A's method, but executed in worldspace so
10162                                 // carried models can be shiny too
10163
10164                                 float viewer[3], d, reflected[3], worldreflected[3];
10165
10166                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10167                                 // VectorNormalize(viewer);
10168
10169                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10170
10171                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10172                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10173                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10174                                 // note: this is proportinal to viewer, so we can normalize later
10175
10176                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10177                                 VectorNormalize(worldreflected);
10178
10179                                 // note: this sphere map only uses world x and z!
10180                                 // so positive and negative y will LOOK THE SAME.
10181                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10182                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10183                         }
10184                         break;
10185                 }
10186                 // the only tcmod that needs software vertex processing is turbulent, so
10187                 // check for it here and apply the changes if needed
10188                 // and we only support that as the first one
10189                 // (handling a mixture of turbulent and other tcmods would be problematic
10190                 //  without punting it entirely to a software path)
10191                 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10192                 {
10193                         amplitude = rsurface.texture->tcmods[0].parms[1];
10194                         animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10195         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10196         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10197         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10198                         for (j = 0;j < batchnumvertices;j++)
10199                         {
10200                                 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);
10201                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10202                         }
10203                 }
10204         }
10205
10206         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10207         {
10208                 // convert the modified arrays to vertex structs
10209 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10210 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10211 //              rsurface.batchvertexmesh_bufferoffset = 0;
10212                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10213                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10214                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10215                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10216                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10217                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10218                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10219                 {
10220                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10221                         {
10222                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10223                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10224                         }
10225                 }
10226                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10227                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10228                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10229                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10230                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10231                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10232                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10233                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10234                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10235                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10236                 {
10237                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10238                         {
10239                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10240                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10241                         }
10242                 }
10243         }
10244
10245         // upload buffer data for the dynamic batch
10246         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10247         {
10248                 if (rsurface.batchvertexmesh)
10249                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10250                 else
10251                 {
10252                         if (rsurface.batchvertex3f)
10253                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10254                         if (rsurface.batchsvector3f)
10255                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10256                         if (rsurface.batchtvector3f)
10257                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10258                         if (rsurface.batchnormal3f)
10259                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10260                         if (rsurface.batchlightmapcolor4f)
10261                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10262                         if (rsurface.batchtexcoordtexture2f)
10263                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10264                         if (rsurface.batchtexcoordlightmap2f)
10265                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10266                         if (rsurface.batchskeletalindex4ub)
10267                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10268                         if (rsurface.batchskeletalweight4ub)
10269                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10270                 }
10271                 if (rsurface.batchelement3s)
10272                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10273                 else if (rsurface.batchelement3i)
10274                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10275         }
10276 }
10277
10278 void RSurf_DrawBatch(void)
10279 {
10280         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10281         // through the pipeline, killing it earlier in the pipeline would have
10282         // per-surface overhead rather than per-batch overhead, so it's best to
10283         // reject it here, before it hits glDraw.
10284         if (rsurface.batchnumtriangles == 0)
10285                 return;
10286 #if 0
10287         // batch debugging code
10288         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10289         {
10290                 int i;
10291                 int j;
10292                 int c;
10293                 const int *e;
10294                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10295                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10296                 {
10297                         c = e[i];
10298                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10299                         {
10300                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10301                                 {
10302                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10303                                                 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);
10304                                         break;
10305                                 }
10306                         }
10307                 }
10308         }
10309 #endif
10310         if (rsurface.batchmultidraw)
10311         {
10312                 // issue multiple draws rather than copying index data
10313                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10314                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10315                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10316                 for (i = 0;i < numsurfaces;)
10317                 {
10318                         // combine consecutive surfaces as one draw
10319                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10320                                 if (surfacelist[j] != surfacelist[k] + 1)
10321                                         break;
10322                         firstvertex = surfacelist[i]->num_firstvertex;
10323                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10324                         firsttriangle = surfacelist[i]->num_firsttriangle;
10325                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10326                         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);
10327                         i = j;
10328                 }
10329         }
10330         else
10331         {
10332                 // there is only one consecutive run of index data (may have been combined)
10333                 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);
10334         }
10335 }
10336
10337 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10338 {
10339         // pick the closest matching water plane
10340         int planeindex, vertexindex, bestplaneindex = -1;
10341         float d, bestd;
10342         vec3_t vert;
10343         const float *v;
10344         r_waterstate_waterplane_t *p;
10345         qboolean prepared = false;
10346         bestd = 0;
10347         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10348         {
10349                 if(p->camera_entity != rsurface.texture->camera_entity)
10350                         continue;
10351                 d = 0;
10352                 if(!prepared)
10353                 {
10354                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10355                         prepared = true;
10356                         if(rsurface.batchnumvertices == 0)
10357                                 break;
10358                 }
10359                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10360                 {
10361                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10362                         d += fabs(PlaneDiff(vert, &p->plane));
10363                 }
10364                 if (bestd > d || bestplaneindex < 0)
10365                 {
10366                         bestd = d;
10367                         bestplaneindex = planeindex;
10368                 }
10369         }
10370         return bestplaneindex;
10371         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10372         // this situation though, as it might be better to render single larger
10373         // batches with useless stuff (backface culled for example) than to
10374         // render multiple smaller batches
10375 }
10376
10377 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10378 {
10379         int i;
10380         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10381         rsurface.passcolor4f_vertexbuffer = 0;
10382         rsurface.passcolor4f_bufferoffset = 0;
10383         for (i = 0;i < rsurface.batchnumvertices;i++)
10384                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10385 }
10386
10387 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10388 {
10389         int i;
10390         float f;
10391         const float *v;
10392         const float *c;
10393         float *c2;
10394         if (rsurface.passcolor4f)
10395         {
10396                 // generate color arrays
10397                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10398                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10399                 rsurface.passcolor4f_vertexbuffer = 0;
10400                 rsurface.passcolor4f_bufferoffset = 0;
10401                 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)
10402                 {
10403                         f = RSurf_FogVertex(v);
10404                         c2[0] = c[0] * f;
10405                         c2[1] = c[1] * f;
10406                         c2[2] = c[2] * f;
10407                         c2[3] = c[3];
10408                 }
10409         }
10410         else
10411         {
10412                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10413                 rsurface.passcolor4f_vertexbuffer = 0;
10414                 rsurface.passcolor4f_bufferoffset = 0;
10415                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10416                 {
10417                         f = RSurf_FogVertex(v);
10418                         c2[0] = f;
10419                         c2[1] = f;
10420                         c2[2] = f;
10421                         c2[3] = 1;
10422                 }
10423         }
10424 }
10425
10426 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10427 {
10428         int i;
10429         float f;
10430         const float *v;
10431         const float *c;
10432         float *c2;
10433         if (!rsurface.passcolor4f)
10434                 return;
10435         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10436         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10437         rsurface.passcolor4f_vertexbuffer = 0;
10438         rsurface.passcolor4f_bufferoffset = 0;
10439         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)
10440         {
10441                 f = RSurf_FogVertex(v);
10442                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10443                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10444                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10445                 c2[3] = c[3];
10446         }
10447 }
10448
10449 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10450 {
10451         int i;
10452         const float *c;
10453         float *c2;
10454         if (!rsurface.passcolor4f)
10455                 return;
10456         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10457         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10458         rsurface.passcolor4f_vertexbuffer = 0;
10459         rsurface.passcolor4f_bufferoffset = 0;
10460         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10461         {
10462                 c2[0] = c[0] * r;
10463                 c2[1] = c[1] * g;
10464                 c2[2] = c[2] * b;
10465                 c2[3] = c[3] * a;
10466         }
10467 }
10468
10469 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10470 {
10471         int i;
10472         const float *c;
10473         float *c2;
10474         if (!rsurface.passcolor4f)
10475                 return;
10476         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10477         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10478         rsurface.passcolor4f_vertexbuffer = 0;
10479         rsurface.passcolor4f_bufferoffset = 0;
10480         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10481         {
10482                 c2[0] = c[0] + r_refdef.scene.ambient;
10483                 c2[1] = c[1] + r_refdef.scene.ambient;
10484                 c2[2] = c[2] + r_refdef.scene.ambient;
10485                 c2[3] = c[3];
10486         }
10487 }
10488
10489 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10490 {
10491         // TODO: optimize
10492         rsurface.passcolor4f = NULL;
10493         rsurface.passcolor4f_vertexbuffer = 0;
10494         rsurface.passcolor4f_bufferoffset = 0;
10495         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10496         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10497         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10498         GL_Color(r, g, b, a);
10499         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10500         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10501         R_Mesh_TexMatrix(0, NULL);
10502         RSurf_DrawBatch();
10503 }
10504
10505 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10506 {
10507         // TODO: optimize applyfog && applycolor case
10508         // just apply fog if necessary, and tint the fog color array if necessary
10509         rsurface.passcolor4f = NULL;
10510         rsurface.passcolor4f_vertexbuffer = 0;
10511         rsurface.passcolor4f_bufferoffset = 0;
10512         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10513         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10514         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10515         GL_Color(r, g, b, a);
10516         RSurf_DrawBatch();
10517 }
10518
10519 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10520 {
10521         // TODO: optimize
10522         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10523         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10524         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10525         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10526         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10527         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10528         GL_Color(r, g, b, a);
10529         RSurf_DrawBatch();
10530 }
10531
10532 static void RSurf_DrawBatch_GL11_ClampColor(void)
10533 {
10534         int i;
10535         const float *c1;
10536         float *c2;
10537         if (!rsurface.passcolor4f)
10538                 return;
10539         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10540         {
10541                 c2[0] = bound(0.0f, c1[0], 1.0f);
10542                 c2[1] = bound(0.0f, c1[1], 1.0f);
10543                 c2[2] = bound(0.0f, c1[2], 1.0f);
10544                 c2[3] = bound(0.0f, c1[3], 1.0f);
10545         }
10546 }
10547
10548 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10549 {
10550         int i;
10551         float f;
10552         const float *v;
10553         const float *n;
10554         float *c;
10555         //vec3_t eyedir;
10556
10557         // fake shading
10558         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10559         rsurface.passcolor4f_vertexbuffer = 0;
10560         rsurface.passcolor4f_bufferoffset = 0;
10561         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)
10562         {
10563                 f = -DotProduct(r_refdef.view.forward, n);
10564                 f = max(0, f);
10565                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10566                 f *= r_refdef.lightmapintensity;
10567                 Vector4Set(c, f, f, f, 1);
10568         }
10569 }
10570
10571 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10572 {
10573         RSurf_DrawBatch_GL11_ApplyFakeLight();
10574         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10575         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10576         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10577         GL_Color(r, g, b, a);
10578         RSurf_DrawBatch();
10579 }
10580
10581 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10582 {
10583         int i;
10584         float f;
10585         float alpha;
10586         const float *v;
10587         const float *n;
10588         float *c;
10589         vec3_t ambientcolor;
10590         vec3_t diffusecolor;
10591         vec3_t lightdir;
10592         // TODO: optimize
10593         // model lighting
10594         VectorCopy(rsurface.modellight_lightdir, lightdir);
10595         f = 0.5f * r_refdef.lightmapintensity;
10596         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10597         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10598         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10599         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10600         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10601         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10602         alpha = *a;
10603         if (VectorLength2(diffusecolor) > 0)
10604         {
10605                 // q3-style directional shading
10606                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10607                 rsurface.passcolor4f_vertexbuffer = 0;
10608                 rsurface.passcolor4f_bufferoffset = 0;
10609                 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)
10610                 {
10611                         if ((f = DotProduct(n, lightdir)) > 0)
10612                                 VectorMA(ambientcolor, f, diffusecolor, c);
10613                         else
10614                                 VectorCopy(ambientcolor, c);
10615                         c[3] = alpha;
10616                 }
10617                 *r = 1;
10618                 *g = 1;
10619                 *b = 1;
10620                 *a = 1;
10621                 *applycolor = false;
10622         }
10623         else
10624         {
10625                 *r = ambientcolor[0];
10626                 *g = ambientcolor[1];
10627                 *b = ambientcolor[2];
10628                 rsurface.passcolor4f = NULL;
10629                 rsurface.passcolor4f_vertexbuffer = 0;
10630                 rsurface.passcolor4f_bufferoffset = 0;
10631         }
10632 }
10633
10634 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10635 {
10636         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10637         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10638         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10639         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10640         GL_Color(r, g, b, a);
10641         RSurf_DrawBatch();
10642 }
10643
10644 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10645 {
10646         int i;
10647         float f;
10648         const float *v;
10649         float *c;
10650
10651         // fake shading
10652         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10653         rsurface.passcolor4f_vertexbuffer = 0;
10654         rsurface.passcolor4f_bufferoffset = 0;
10655
10656         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10657         {
10658                 f = 1 - RSurf_FogVertex(v);
10659                 c[0] = r;
10660                 c[1] = g;
10661                 c[2] = b;
10662                 c[3] = f * a;
10663         }
10664 }
10665
10666 void RSurf_SetupDepthAndCulling(void)
10667 {
10668         // submodels are biased to avoid z-fighting with world surfaces that they
10669         // may be exactly overlapping (avoids z-fighting artifacts on certain
10670         // doors and things in Quake maps)
10671         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10672         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10673         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10674         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10675 }
10676
10677 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10678 {
10679         // transparent sky would be ridiculous
10680         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10681                 return;
10682         R_SetupShader_Generic_NoTexture(false, false);
10683         skyrenderlater = true;
10684         RSurf_SetupDepthAndCulling();
10685         GL_DepthMask(true);
10686         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10687         // skymasking on them, and Quake3 never did sky masking (unlike
10688         // software Quake and software Quake2), so disable the sky masking
10689         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10690         // and skymasking also looks very bad when noclipping outside the
10691         // level, so don't use it then either.
10692         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10693         {
10694                 R_Mesh_ResetTextureState();
10695                 if (skyrendermasked)
10696                 {
10697                         R_SetupShader_DepthOrShadow(false, false, false);
10698                         // depth-only (masking)
10699                         GL_ColorMask(0,0,0,0);
10700                         // just to make sure that braindead drivers don't draw
10701                         // anything despite that colormask...
10702                         GL_BlendFunc(GL_ZERO, GL_ONE);
10703                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10704                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10705                 }
10706                 else
10707                 {
10708                         R_SetupShader_Generic_NoTexture(false, false);
10709                         // fog sky
10710                         GL_BlendFunc(GL_ONE, GL_ZERO);
10711                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10712                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10713                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10714                 }
10715                 RSurf_DrawBatch();
10716                 if (skyrendermasked)
10717                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10718         }
10719         R_Mesh_ResetTextureState();
10720         GL_Color(1, 1, 1, 1);
10721 }
10722
10723 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10724 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10725 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10726 {
10727         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10728                 return;
10729         if (prepass)
10730         {
10731                 // render screenspace normalmap to texture
10732                 GL_DepthMask(true);
10733                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10734                 RSurf_DrawBatch();
10735                 return;
10736         }
10737
10738         // bind lightmap texture
10739
10740         // water/refraction/reflection/camera surfaces have to be handled specially
10741         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10742         {
10743                 int start, end, startplaneindex;
10744                 for (start = 0;start < texturenumsurfaces;start = end)
10745                 {
10746                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10747                         if(startplaneindex < 0)
10748                         {
10749                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10750                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10751                                 end = start + 1;
10752                                 continue;
10753                         }
10754                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10755                                 ;
10756                         // now that we have a batch using the same planeindex, render it
10757                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10758                         {
10759                                 // render water or distortion background
10760                                 GL_DepthMask(true);
10761                                 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);
10762                                 RSurf_DrawBatch();
10763                                 // blend surface on top
10764                                 GL_DepthMask(false);
10765                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10766                                 RSurf_DrawBatch();
10767                         }
10768                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10769                         {
10770                                 // render surface with reflection texture as input
10771                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10772                                 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);
10773                                 RSurf_DrawBatch();
10774                         }
10775                 }
10776                 return;
10777         }
10778
10779         // render surface batch normally
10780         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10781         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);
10782         RSurf_DrawBatch();
10783 }
10784
10785 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10786 {
10787         // OpenGL 1.3 path - anything not completely ancient
10788         qboolean applycolor;
10789         qboolean applyfog;
10790         int layerindex;
10791         const texturelayer_t *layer;
10792         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);
10793         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10794
10795         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10796         {
10797                 vec4_t layercolor;
10798                 int layertexrgbscale;
10799                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10800                 {
10801                         if (layerindex == 0)
10802                                 GL_AlphaTest(true);
10803                         else
10804                         {
10805                                 GL_AlphaTest(false);
10806                                 GL_DepthFunc(GL_EQUAL);
10807                         }
10808                 }
10809                 GL_DepthMask(layer->depthmask && writedepth);
10810                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10811                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10812                 {
10813                         layertexrgbscale = 4;
10814                         VectorScale(layer->color, 0.25f, layercolor);
10815                 }
10816                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10817                 {
10818                         layertexrgbscale = 2;
10819                         VectorScale(layer->color, 0.5f, layercolor);
10820                 }
10821                 else
10822                 {
10823                         layertexrgbscale = 1;
10824                         VectorScale(layer->color, 1.0f, layercolor);
10825                 }
10826                 layercolor[3] = layer->color[3];
10827                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10828                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10829                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10830                 switch (layer->type)
10831                 {
10832                 case TEXTURELAYERTYPE_LITTEXTURE:
10833                         // single-pass lightmapped texture with 2x rgbscale
10834                         R_Mesh_TexBind(0, r_texture_white);
10835                         R_Mesh_TexMatrix(0, NULL);
10836                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10837                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10838                         R_Mesh_TexBind(1, layer->texture);
10839                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10840                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10841                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10842                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10843                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10844                         else if (FAKELIGHT_ENABLED)
10845                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10846                         else if (rsurface.uselightmaptexture)
10847                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10848                         else
10849                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10850                         break;
10851                 case TEXTURELAYERTYPE_TEXTURE:
10852                         // singletexture unlit texture with transparency support
10853                         R_Mesh_TexBind(0, layer->texture);
10854                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10855                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10856                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10857                         R_Mesh_TexBind(1, 0);
10858                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10859                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10860                         break;
10861                 case TEXTURELAYERTYPE_FOG:
10862                         // singletexture fogging
10863                         if (layer->texture)
10864                         {
10865                                 R_Mesh_TexBind(0, layer->texture);
10866                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10867                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10868                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10869                         }
10870                         else
10871                         {
10872                                 R_Mesh_TexBind(0, 0);
10873                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10874                         }
10875                         R_Mesh_TexBind(1, 0);
10876                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10877                         // generate a color array for the fog pass
10878                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10879                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10880                         RSurf_DrawBatch();
10881                         break;
10882                 default:
10883                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10884                 }
10885         }
10886         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10887         {
10888                 GL_DepthFunc(GL_LEQUAL);
10889                 GL_AlphaTest(false);
10890         }
10891 }
10892
10893 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10894 {
10895         // OpenGL 1.1 - crusty old voodoo path
10896         qboolean applyfog;
10897         int layerindex;
10898         const texturelayer_t *layer;
10899         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);
10900         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10901
10902         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10903         {
10904                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10905                 {
10906                         if (layerindex == 0)
10907                                 GL_AlphaTest(true);
10908                         else
10909                         {
10910                                 GL_AlphaTest(false);
10911                                 GL_DepthFunc(GL_EQUAL);
10912                         }
10913                 }
10914                 GL_DepthMask(layer->depthmask && writedepth);
10915                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10916                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10917                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10918                 switch (layer->type)
10919                 {
10920                 case TEXTURELAYERTYPE_LITTEXTURE:
10921                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10922                         {
10923                                 // two-pass lit texture with 2x rgbscale
10924                                 // first the lightmap pass
10925                                 R_Mesh_TexBind(0, r_texture_white);
10926                                 R_Mesh_TexMatrix(0, NULL);
10927                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10928                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10929                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10930                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10931                                 else if (FAKELIGHT_ENABLED)
10932                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10933                                 else if (rsurface.uselightmaptexture)
10934                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10935                                 else
10936                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10937                                 // then apply the texture to it
10938                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10939                                 R_Mesh_TexBind(0, layer->texture);
10940                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10941                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10942                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10943                                 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);
10944                         }
10945                         else
10946                         {
10947                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10948                                 R_Mesh_TexBind(0, layer->texture);
10949                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10950                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10951                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10952                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10953                                         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);
10954                                 else if (FAKELIGHT_ENABLED)
10955                                         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);
10956                                 else
10957                                         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);
10958                         }
10959                         break;
10960                 case TEXTURELAYERTYPE_TEXTURE:
10961                         // singletexture unlit texture with transparency support
10962                         R_Mesh_TexBind(0, layer->texture);
10963                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10964                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10965                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10966                         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);
10967                         break;
10968                 case TEXTURELAYERTYPE_FOG:
10969                         // singletexture fogging
10970                         if (layer->texture)
10971                         {
10972                                 R_Mesh_TexBind(0, layer->texture);
10973                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10974                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10975                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10976                         }
10977                         else
10978                         {
10979                                 R_Mesh_TexBind(0, 0);
10980                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10981                         }
10982                         // generate a color array for the fog pass
10983                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10984                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10985                         RSurf_DrawBatch();
10986                         break;
10987                 default:
10988                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10989                 }
10990         }
10991         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10992         {
10993                 GL_DepthFunc(GL_LEQUAL);
10994                 GL_AlphaTest(false);
10995         }
10996 }
10997
10998 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10999 {
11000         int vi;
11001         int j;
11002         r_vertexgeneric_t *batchvertex;
11003         float c[4];
11004
11005 //      R_Mesh_ResetTextureState();
11006         R_SetupShader_Generic_NoTexture(false, false);
11007
11008         if(rsurface.texture && rsurface.texture->currentskinframe)
11009         {
11010                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11011                 c[3] *= rsurface.texture->currentalpha;
11012         }
11013         else
11014         {
11015                 c[0] = 1;
11016                 c[1] = 0;
11017                 c[2] = 1;
11018                 c[3] = 1;
11019         }
11020
11021         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11022         {
11023                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11024                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11025                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11026         }
11027
11028         // brighten it up (as texture value 127 means "unlit")
11029         c[0] *= 2 * r_refdef.view.colorscale;
11030         c[1] *= 2 * r_refdef.view.colorscale;
11031         c[2] *= 2 * r_refdef.view.colorscale;
11032
11033         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11034                 c[3] *= r_wateralpha.value;
11035
11036         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11037         {
11038                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11039                 GL_DepthMask(false);
11040         }
11041         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11042         {
11043                 GL_BlendFunc(GL_ONE, GL_ONE);
11044                 GL_DepthMask(false);
11045         }
11046         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11047         {
11048                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11049                 GL_DepthMask(false);
11050         }
11051         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11052         {
11053                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11054                 GL_DepthMask(false);
11055         }
11056         else
11057         {
11058                 GL_BlendFunc(GL_ONE, GL_ZERO);
11059                 GL_DepthMask(writedepth);
11060         }
11061
11062         if (r_showsurfaces.integer == 3)
11063         {
11064                 rsurface.passcolor4f = NULL;
11065
11066                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11067                 {
11068                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11069
11070                         rsurface.passcolor4f = NULL;
11071                         rsurface.passcolor4f_vertexbuffer = 0;
11072                         rsurface.passcolor4f_bufferoffset = 0;
11073                 }
11074                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11075                 {
11076                         qboolean applycolor = true;
11077                         float one = 1.0;
11078
11079                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11080
11081                         r_refdef.lightmapintensity = 1;
11082                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11083                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11084                 }
11085                 else if (FAKELIGHT_ENABLED)
11086                 {
11087                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11088
11089                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11090                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11091                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11092                 }
11093                 else
11094                 {
11095                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11096
11097                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11098                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11099                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11100                 }
11101
11102                 if(!rsurface.passcolor4f)
11103                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11104
11105                 RSurf_DrawBatch_GL11_ApplyAmbient();
11106                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11107                 if(r_refdef.fogenabled)
11108                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11109                 RSurf_DrawBatch_GL11_ClampColor();
11110
11111                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11112                 R_SetupShader_Generic_NoTexture(false, false);
11113                 RSurf_DrawBatch();
11114         }
11115         else if (!r_refdef.view.showdebug)
11116         {
11117                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11118                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11119                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11120                 {
11121                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11122                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11123                 }
11124                 R_Mesh_PrepareVertices_Generic_Unlock();
11125                 RSurf_DrawBatch();
11126         }
11127         else if (r_showsurfaces.integer == 4)
11128         {
11129                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11130                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11131                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11132                 {
11133                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11134                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11135                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11136                 }
11137                 R_Mesh_PrepareVertices_Generic_Unlock();
11138                 RSurf_DrawBatch();
11139         }
11140         else if (r_showsurfaces.integer == 2)
11141         {
11142                 const int *e;
11143                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11144                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11145                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11146                 {
11147                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11148                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11149                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11150                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11151                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11152                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11153                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11154                 }
11155                 R_Mesh_PrepareVertices_Generic_Unlock();
11156                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11157         }
11158         else
11159         {
11160                 int texturesurfaceindex;
11161                 int k;
11162                 const msurface_t *surface;
11163                 float surfacecolor4f[4];
11164                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11165                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11166                 vi = 0;
11167                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11168                 {
11169                         surface = texturesurfacelist[texturesurfaceindex];
11170                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11171                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11172                         for (j = 0;j < surface->num_vertices;j++)
11173                         {
11174                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11175                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11176                                 vi++;
11177                         }
11178                 }
11179                 R_Mesh_PrepareVertices_Generic_Unlock();
11180                 RSurf_DrawBatch();
11181         }
11182 }
11183
11184 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11185 {
11186         CHECKGLERROR
11187         RSurf_SetupDepthAndCulling();
11188         if (r_showsurfaces.integer)
11189         {
11190                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11191                 return;
11192         }
11193         switch (vid.renderpath)
11194         {
11195         case RENDERPATH_GL20:
11196         case RENDERPATH_D3D9:
11197         case RENDERPATH_D3D10:
11198         case RENDERPATH_D3D11:
11199         case RENDERPATH_SOFT:
11200         case RENDERPATH_GLES2:
11201                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11202                 break;
11203         case RENDERPATH_GL13:
11204         case RENDERPATH_GLES1:
11205                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11206                 break;
11207         case RENDERPATH_GL11:
11208                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11209                 break;
11210         }
11211         CHECKGLERROR
11212 }
11213
11214 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11215 {
11216         CHECKGLERROR
11217         RSurf_SetupDepthAndCulling();
11218         if (r_showsurfaces.integer)
11219         {
11220                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11221                 return;
11222         }
11223         switch (vid.renderpath)
11224         {
11225         case RENDERPATH_GL20:
11226         case RENDERPATH_D3D9:
11227         case RENDERPATH_D3D10:
11228         case RENDERPATH_D3D11:
11229         case RENDERPATH_SOFT:
11230         case RENDERPATH_GLES2:
11231                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11232                 break;
11233         case RENDERPATH_GL13:
11234         case RENDERPATH_GLES1:
11235                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11236                 break;
11237         case RENDERPATH_GL11:
11238                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11239                 break;
11240         }
11241         CHECKGLERROR
11242 }
11243
11244 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11245 {
11246         int i, j;
11247         int texturenumsurfaces, endsurface;
11248         texture_t *texture;
11249         const msurface_t *surface;
11250         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11251
11252         // if the model is static it doesn't matter what value we give for
11253         // wantnormals and wanttangents, so this logic uses only rules applicable
11254         // to a model, knowing that they are meaningless otherwise
11255         if (ent == r_refdef.scene.worldentity)
11256                 RSurf_ActiveWorldEntity();
11257         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11258                 RSurf_ActiveModelEntity(ent, false, false, false);
11259         else
11260         {
11261                 switch (vid.renderpath)
11262                 {
11263                 case RENDERPATH_GL20:
11264                 case RENDERPATH_D3D9:
11265                 case RENDERPATH_D3D10:
11266                 case RENDERPATH_D3D11:
11267                 case RENDERPATH_SOFT:
11268                 case RENDERPATH_GLES2:
11269                         RSurf_ActiveModelEntity(ent, true, true, false);
11270                         break;
11271                 case RENDERPATH_GL11:
11272                 case RENDERPATH_GL13:
11273                 case RENDERPATH_GLES1:
11274                         RSurf_ActiveModelEntity(ent, true, false, false);
11275                         break;
11276                 }
11277         }
11278
11279         if (r_transparentdepthmasking.integer)
11280         {
11281                 qboolean setup = false;
11282                 for (i = 0;i < numsurfaces;i = j)
11283                 {
11284                         j = i + 1;
11285                         surface = rsurface.modelsurfaces + surfacelist[i];
11286                         texture = surface->texture;
11287                         rsurface.texture = R_GetCurrentTexture(texture);
11288                         rsurface.lightmaptexture = NULL;
11289                         rsurface.deluxemaptexture = NULL;
11290                         rsurface.uselightmaptexture = false;
11291                         // scan ahead until we find a different texture
11292                         endsurface = min(i + 1024, numsurfaces);
11293                         texturenumsurfaces = 0;
11294                         texturesurfacelist[texturenumsurfaces++] = surface;
11295                         for (;j < endsurface;j++)
11296                         {
11297                                 surface = rsurface.modelsurfaces + surfacelist[j];
11298                                 if (texture != surface->texture)
11299                                         break;
11300                                 texturesurfacelist[texturenumsurfaces++] = surface;
11301                         }
11302                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11303                                 continue;
11304                         // render the range of surfaces as depth
11305                         if (!setup)
11306                         {
11307                                 setup = true;
11308                                 GL_ColorMask(0,0,0,0);
11309                                 GL_Color(1,1,1,1);
11310                                 GL_DepthTest(true);
11311                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11312                                 GL_DepthMask(true);
11313 //                              R_Mesh_ResetTextureState();
11314                         }
11315                         RSurf_SetupDepthAndCulling();
11316                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11317                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11318                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11319                         RSurf_DrawBatch();
11320                 }
11321                 if (setup)
11322                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11323         }
11324
11325         for (i = 0;i < numsurfaces;i = j)
11326         {
11327                 j = i + 1;
11328                 surface = rsurface.modelsurfaces + surfacelist[i];
11329                 texture = surface->texture;
11330                 rsurface.texture = R_GetCurrentTexture(texture);
11331                 // scan ahead until we find a different texture
11332                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11333                 texturenumsurfaces = 0;
11334                 texturesurfacelist[texturenumsurfaces++] = surface;
11335                 if(FAKELIGHT_ENABLED)
11336                 {
11337                         rsurface.lightmaptexture = NULL;
11338                         rsurface.deluxemaptexture = NULL;
11339                         rsurface.uselightmaptexture = false;
11340                         for (;j < endsurface;j++)
11341                         {
11342                                 surface = rsurface.modelsurfaces + surfacelist[j];
11343                                 if (texture != surface->texture)
11344                                         break;
11345                                 texturesurfacelist[texturenumsurfaces++] = surface;
11346                         }
11347                 }
11348                 else
11349                 {
11350                         rsurface.lightmaptexture = surface->lightmaptexture;
11351                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11352                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11353                         for (;j < endsurface;j++)
11354                         {
11355                                 surface = rsurface.modelsurfaces + surfacelist[j];
11356                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11357                                         break;
11358                                 texturesurfacelist[texturenumsurfaces++] = surface;
11359                         }
11360                 }
11361                 // render the range of surfaces
11362                 if (ent == r_refdef.scene.worldentity)
11363                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11364                 else
11365                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11366         }
11367         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11368 }
11369
11370 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11371 {
11372         // transparent surfaces get pushed off into the transparent queue
11373         int surfacelistindex;
11374         const msurface_t *surface;
11375         vec3_t tempcenter, center;
11376         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11377         {
11378                 surface = texturesurfacelist[surfacelistindex];
11379                 if (r_transparent_sortsurfacesbynearest.integer)
11380                 {
11381                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11382                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11383                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11384                 }
11385                 else
11386                 {
11387                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11388                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11389                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11390                 }
11391                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11392                 if (rsurface.entity->transparent_offset) // transparent offset
11393                 {
11394                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11395                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11396                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11397                 }
11398                 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);
11399         }
11400 }
11401
11402 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11403 {
11404         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11405                 return;
11406         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11407                 return;
11408         RSurf_SetupDepthAndCulling();
11409         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11410         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11411         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11412         RSurf_DrawBatch();
11413 }
11414
11415 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11416 {
11417         CHECKGLERROR
11418         if (depthonly)
11419                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11420         else if (prepass)
11421         {
11422                 if (!rsurface.texture->currentnumlayers)
11423                         return;
11424                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11425                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11426                 else
11427                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11428         }
11429         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11430                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11431         else if (!rsurface.texture->currentnumlayers)
11432                 return;
11433         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11434         {
11435                 // in the deferred case, transparent surfaces were queued during prepass
11436                 if (!r_shadow_usingdeferredprepass)
11437                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11438         }
11439         else
11440         {
11441                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11442                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11443         }
11444         CHECKGLERROR
11445 }
11446
11447 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11448 {
11449         int i, j;
11450         texture_t *texture;
11451         R_FrameData_SetMark();
11452         // break the surface list down into batches by texture and use of lightmapping
11453         for (i = 0;i < numsurfaces;i = j)
11454         {
11455                 j = i + 1;
11456                 // texture is the base texture pointer, rsurface.texture is the
11457                 // current frame/skin the texture is directing us to use (for example
11458                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11459                 // use skin 1 instead)
11460                 texture = surfacelist[i]->texture;
11461                 rsurface.texture = R_GetCurrentTexture(texture);
11462                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11463                 {
11464                         // if this texture is not the kind we want, skip ahead to the next one
11465                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11466                                 ;
11467                         continue;
11468                 }
11469                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11470                 {
11471                         rsurface.lightmaptexture = NULL;
11472                         rsurface.deluxemaptexture = NULL;
11473                         rsurface.uselightmaptexture = false;
11474                         // simply scan ahead until we find a different texture or lightmap state
11475                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11476                                 ;
11477                 }
11478                 else
11479                 {
11480                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11481                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11482                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11483                         // simply scan ahead until we find a different texture or lightmap state
11484                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11485                                 ;
11486                 }
11487                 // render the range of surfaces
11488                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11489         }
11490         R_FrameData_ReturnToMark();
11491 }
11492
11493 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11494 {
11495         CHECKGLERROR
11496         if (depthonly)
11497                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11498         else if (prepass)
11499         {
11500                 if (!rsurface.texture->currentnumlayers)
11501                         return;
11502                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11503                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11504                 else
11505                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11506         }
11507         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11508                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11509         else if (!rsurface.texture->currentnumlayers)
11510                 return;
11511         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11512         {
11513                 // in the deferred case, transparent surfaces were queued during prepass
11514                 if (!r_shadow_usingdeferredprepass)
11515                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11516         }
11517         else
11518         {
11519                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11520                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11521         }
11522         CHECKGLERROR
11523 }
11524
11525 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11526 {
11527         int i, j;
11528         texture_t *texture;
11529         R_FrameData_SetMark();
11530         // break the surface list down into batches by texture and use of lightmapping
11531         for (i = 0;i < numsurfaces;i = j)
11532         {
11533                 j = i + 1;
11534                 // texture is the base texture pointer, rsurface.texture is the
11535                 // current frame/skin the texture is directing us to use (for example
11536                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11537                 // use skin 1 instead)
11538                 texture = surfacelist[i]->texture;
11539                 rsurface.texture = R_GetCurrentTexture(texture);
11540                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11541                 {
11542                         // if this texture is not the kind we want, skip ahead to the next one
11543                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11544                                 ;
11545                         continue;
11546                 }
11547                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11548                 {
11549                         rsurface.lightmaptexture = NULL;
11550                         rsurface.deluxemaptexture = NULL;
11551                         rsurface.uselightmaptexture = false;
11552                         // simply scan ahead until we find a different texture or lightmap state
11553                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11554                                 ;
11555                 }
11556                 else
11557                 {
11558                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11559                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11560                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11561                         // simply scan ahead until we find a different texture or lightmap state
11562                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11563                                 ;
11564                 }
11565                 // render the range of surfaces
11566                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11567         }
11568         R_FrameData_ReturnToMark();
11569 }
11570
11571 float locboxvertex3f[6*4*3] =
11572 {
11573         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11574         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11575         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11576         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11577         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11578         1,0,0, 0,0,0, 0,1,0, 1,1,0
11579 };
11580
11581 unsigned short locboxelements[6*2*3] =
11582 {
11583          0, 1, 2, 0, 2, 3,
11584          4, 5, 6, 4, 6, 7,
11585          8, 9,10, 8,10,11,
11586         12,13,14, 12,14,15,
11587         16,17,18, 16,18,19,
11588         20,21,22, 20,22,23
11589 };
11590
11591 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11592 {
11593         int i, j;
11594         cl_locnode_t *loc = (cl_locnode_t *)ent;
11595         vec3_t mins, size;
11596         float vertex3f[6*4*3];
11597         CHECKGLERROR
11598         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11599         GL_DepthMask(false);
11600         GL_DepthRange(0, 1);
11601         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11602         GL_DepthTest(true);
11603         GL_CullFace(GL_NONE);
11604         R_EntityMatrix(&identitymatrix);
11605
11606 //      R_Mesh_ResetTextureState();
11607
11608         i = surfacelist[0];
11609         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11610                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11611                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11612                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11613
11614         if (VectorCompare(loc->mins, loc->maxs))
11615         {
11616                 VectorSet(size, 2, 2, 2);
11617                 VectorMA(loc->mins, -0.5f, size, mins);
11618         }
11619         else
11620         {
11621                 VectorCopy(loc->mins, mins);
11622                 VectorSubtract(loc->maxs, loc->mins, size);
11623         }
11624
11625         for (i = 0;i < 6*4*3;)
11626                 for (j = 0;j < 3;j++, i++)
11627                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11628
11629         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11630         R_SetupShader_Generic_NoTexture(false, false);
11631         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11632 }
11633
11634 void R_DrawLocs(void)
11635 {
11636         int index;
11637         cl_locnode_t *loc, *nearestloc;
11638         vec3_t center;
11639         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11640         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11641         {
11642                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11643                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11644         }
11645 }
11646
11647 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11648 {
11649         if (decalsystem->decals)
11650                 Mem_Free(decalsystem->decals);
11651         memset(decalsystem, 0, sizeof(*decalsystem));
11652 }
11653
11654 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)
11655 {
11656         tridecal_t *decal;
11657         tridecal_t *decals;
11658         int i;
11659
11660         // expand or initialize the system
11661         if (decalsystem->maxdecals <= decalsystem->numdecals)
11662         {
11663                 decalsystem_t old = *decalsystem;
11664                 qboolean useshortelements;
11665                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11666                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11667                 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)));
11668                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11669                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11670                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11671                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11672                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11673                 if (decalsystem->numdecals)
11674                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11675                 if (old.decals)
11676                         Mem_Free(old.decals);
11677                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11678                         decalsystem->element3i[i] = i;
11679                 if (useshortelements)
11680                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11681                                 decalsystem->element3s[i] = i;
11682         }
11683
11684         // grab a decal and search for another free slot for the next one
11685         decals = decalsystem->decals;
11686         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11687         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11688                 ;
11689         decalsystem->freedecal = i;
11690         if (decalsystem->numdecals <= i)
11691                 decalsystem->numdecals = i + 1;
11692
11693         // initialize the decal
11694         decal->lived = 0;
11695         decal->triangleindex = triangleindex;
11696         decal->surfaceindex = surfaceindex;
11697         decal->decalsequence = decalsequence;
11698         decal->color4f[0][0] = c0[0];
11699         decal->color4f[0][1] = c0[1];
11700         decal->color4f[0][2] = c0[2];
11701         decal->color4f[0][3] = 1;
11702         decal->color4f[1][0] = c1[0];
11703         decal->color4f[1][1] = c1[1];
11704         decal->color4f[1][2] = c1[2];
11705         decal->color4f[1][3] = 1;
11706         decal->color4f[2][0] = c2[0];
11707         decal->color4f[2][1] = c2[1];
11708         decal->color4f[2][2] = c2[2];
11709         decal->color4f[2][3] = 1;
11710         decal->vertex3f[0][0] = v0[0];
11711         decal->vertex3f[0][1] = v0[1];
11712         decal->vertex3f[0][2] = v0[2];
11713         decal->vertex3f[1][0] = v1[0];
11714         decal->vertex3f[1][1] = v1[1];
11715         decal->vertex3f[1][2] = v1[2];
11716         decal->vertex3f[2][0] = v2[0];
11717         decal->vertex3f[2][1] = v2[1];
11718         decal->vertex3f[2][2] = v2[2];
11719         decal->texcoord2f[0][0] = t0[0];
11720         decal->texcoord2f[0][1] = t0[1];
11721         decal->texcoord2f[1][0] = t1[0];
11722         decal->texcoord2f[1][1] = t1[1];
11723         decal->texcoord2f[2][0] = t2[0];
11724         decal->texcoord2f[2][1] = t2[1];
11725         TriangleNormal(v0, v1, v2, decal->plane);
11726         VectorNormalize(decal->plane);
11727         decal->plane[3] = DotProduct(v0, decal->plane);
11728 }
11729
11730 extern cvar_t cl_decals_bias;
11731 extern cvar_t cl_decals_models;
11732 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11733 // baseparms, parms, temps
11734 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)
11735 {
11736         int cornerindex;
11737         int index;
11738         float v[9][3];
11739         const float *vertex3f;
11740         const float *normal3f;
11741         int numpoints;
11742         float points[2][9][3];
11743         float temp[3];
11744         float tc[9][2];
11745         float f;
11746         float c[9][4];
11747         const int *e;
11748
11749         e = rsurface.modelelement3i + 3*triangleindex;
11750
11751         vertex3f = rsurface.modelvertex3f;
11752         normal3f = rsurface.modelnormal3f;
11753
11754         if (normal3f)
11755         {
11756                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11757                 {
11758                         index = 3*e[cornerindex];
11759                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11760                 }
11761         }
11762         else
11763         {
11764                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11765                 {
11766                         index = 3*e[cornerindex];
11767                         VectorCopy(vertex3f + index, v[cornerindex]);
11768                 }
11769         }
11770
11771         // cull backfaces
11772         //TriangleNormal(v[0], v[1], v[2], normal);
11773         //if (DotProduct(normal, localnormal) < 0.0f)
11774         //      continue;
11775         // clip by each of the box planes formed from the projection matrix
11776         // if anything survives, we emit the decal
11777         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]);
11778         if (numpoints < 3)
11779                 return;
11780         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]);
11781         if (numpoints < 3)
11782                 return;
11783         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]);
11784         if (numpoints < 3)
11785                 return;
11786         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]);
11787         if (numpoints < 3)
11788                 return;
11789         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]);
11790         if (numpoints < 3)
11791                 return;
11792         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]);
11793         if (numpoints < 3)
11794                 return;
11795         // some part of the triangle survived, so we have to accept it...
11796         if (dynamic)
11797         {
11798                 // dynamic always uses the original triangle
11799                 numpoints = 3;
11800                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11801                 {
11802                         index = 3*e[cornerindex];
11803                         VectorCopy(vertex3f + index, v[cornerindex]);
11804                 }
11805         }
11806         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11807         {
11808                 // convert vertex positions to texcoords
11809                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11810                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11811                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11812                 // calculate distance fade from the projection origin
11813                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11814                 f = bound(0.0f, f, 1.0f);
11815                 c[cornerindex][0] = r * f;
11816                 c[cornerindex][1] = g * f;
11817                 c[cornerindex][2] = b * f;
11818                 c[cornerindex][3] = 1.0f;
11819                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11820         }
11821         if (dynamic)
11822                 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);
11823         else
11824                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11825                         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);
11826 }
11827 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)
11828 {
11829         matrix4x4_t projection;
11830         decalsystem_t *decalsystem;
11831         qboolean dynamic;
11832         dp_model_t *model;
11833         const msurface_t *surface;
11834         const msurface_t *surfaces;
11835         const int *surfacelist;
11836         const texture_t *texture;
11837         int numtriangles;
11838         int numsurfacelist;
11839         int surfacelistindex;
11840         int surfaceindex;
11841         int triangleindex;
11842         float localorigin[3];
11843         float localnormal[3];
11844         float localmins[3];
11845         float localmaxs[3];
11846         float localsize;
11847         //float normal[3];
11848         float planes[6][4];
11849         float angles[3];
11850         bih_t *bih;
11851         int bih_triangles_count;
11852         int bih_triangles[256];
11853         int bih_surfaces[256];
11854
11855         decalsystem = &ent->decalsystem;
11856         model = ent->model;
11857         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11858         {
11859                 R_DecalSystem_Reset(&ent->decalsystem);
11860                 return;
11861         }
11862
11863         if (!model->brush.data_leafs && !cl_decals_models.integer)
11864         {
11865                 if (decalsystem->model)
11866                         R_DecalSystem_Reset(decalsystem);
11867                 return;
11868         }
11869
11870         if (decalsystem->model != model)
11871                 R_DecalSystem_Reset(decalsystem);
11872         decalsystem->model = model;
11873
11874         RSurf_ActiveModelEntity(ent, true, false, false);
11875
11876         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11877         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11878         VectorNormalize(localnormal);
11879         localsize = worldsize*rsurface.inversematrixscale;
11880         localmins[0] = localorigin[0] - localsize;
11881         localmins[1] = localorigin[1] - localsize;
11882         localmins[2] = localorigin[2] - localsize;
11883         localmaxs[0] = localorigin[0] + localsize;
11884         localmaxs[1] = localorigin[1] + localsize;
11885         localmaxs[2] = localorigin[2] + localsize;
11886
11887         //VectorCopy(localnormal, planes[4]);
11888         //VectorVectors(planes[4], planes[2], planes[0]);
11889         AnglesFromVectors(angles, localnormal, NULL, false);
11890         AngleVectors(angles, planes[0], planes[2], planes[4]);
11891         VectorNegate(planes[0], planes[1]);
11892         VectorNegate(planes[2], planes[3]);
11893         VectorNegate(planes[4], planes[5]);
11894         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11895         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11896         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11897         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11898         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11899         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11900
11901 #if 1
11902 // works
11903 {
11904         matrix4x4_t forwardprojection;
11905         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11906         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11907 }
11908 #else
11909 // broken
11910 {
11911         float projectionvector[4][3];
11912         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11913         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11914         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11915         projectionvector[0][0] = planes[0][0] * ilocalsize;
11916         projectionvector[0][1] = planes[1][0] * ilocalsize;
11917         projectionvector[0][2] = planes[2][0] * ilocalsize;
11918         projectionvector[1][0] = planes[0][1] * ilocalsize;
11919         projectionvector[1][1] = planes[1][1] * ilocalsize;
11920         projectionvector[1][2] = planes[2][1] * ilocalsize;
11921         projectionvector[2][0] = planes[0][2] * ilocalsize;
11922         projectionvector[2][1] = planes[1][2] * ilocalsize;
11923         projectionvector[2][2] = planes[2][2] * ilocalsize;
11924         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11925         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11926         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11927         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11928 }
11929 #endif
11930
11931         dynamic = model->surfmesh.isanimated;
11932         numsurfacelist = model->nummodelsurfaces;
11933         surfacelist = model->sortedmodelsurfaces;
11934         surfaces = model->data_surfaces;
11935
11936         bih = NULL;
11937         bih_triangles_count = -1;
11938         if(!dynamic)
11939         {
11940                 if(model->render_bih.numleafs)
11941                         bih = &model->render_bih;
11942                 else if(model->collision_bih.numleafs)
11943                         bih = &model->collision_bih;
11944         }
11945         if(bih)
11946                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11947         if(bih_triangles_count == 0)
11948                 return;
11949         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11950                 return;
11951         if(bih_triangles_count > 0)
11952         {
11953                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11954                 {
11955                         surfaceindex = bih_surfaces[triangleindex];
11956                         surface = surfaces + surfaceindex;
11957                         texture = surface->texture;
11958                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11959                                 continue;
11960                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11961                                 continue;
11962                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11963                 }
11964         }
11965         else
11966         {
11967                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11968                 {
11969                         surfaceindex = surfacelist[surfacelistindex];
11970                         surface = surfaces + surfaceindex;
11971                         // check cull box first because it rejects more than any other check
11972                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11973                                 continue;
11974                         // skip transparent surfaces
11975                         texture = surface->texture;
11976                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11977                                 continue;
11978                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11979                                 continue;
11980                         numtriangles = surface->num_triangles;
11981                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11982                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11983                 }
11984         }
11985 }
11986
11987 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11988 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)
11989 {
11990         int renderentityindex;
11991         float worldmins[3];
11992         float worldmaxs[3];
11993         entity_render_t *ent;
11994
11995         if (!cl_decals_newsystem.integer)
11996                 return;
11997
11998         worldmins[0] = worldorigin[0] - worldsize;
11999         worldmins[1] = worldorigin[1] - worldsize;
12000         worldmins[2] = worldorigin[2] - worldsize;
12001         worldmaxs[0] = worldorigin[0] + worldsize;
12002         worldmaxs[1] = worldorigin[1] + worldsize;
12003         worldmaxs[2] = worldorigin[2] + worldsize;
12004
12005         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12006
12007         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12008         {
12009                 ent = r_refdef.scene.entities[renderentityindex];
12010                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12011                         continue;
12012
12013                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12014         }
12015 }
12016
12017 typedef struct r_decalsystem_splatqueue_s
12018 {
12019         vec3_t worldorigin;
12020         vec3_t worldnormal;
12021         float color[4];
12022         float tcrange[4];
12023         float worldsize;
12024         unsigned int decalsequence;
12025 }
12026 r_decalsystem_splatqueue_t;
12027
12028 int r_decalsystem_numqueued = 0;
12029 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12030
12031 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)
12032 {
12033         r_decalsystem_splatqueue_t *queue;
12034
12035         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12036                 return;
12037
12038         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12039         VectorCopy(worldorigin, queue->worldorigin);
12040         VectorCopy(worldnormal, queue->worldnormal);
12041         Vector4Set(queue->color, r, g, b, a);
12042         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12043         queue->worldsize = worldsize;
12044         queue->decalsequence = cl.decalsequence++;
12045 }
12046
12047 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12048 {
12049         int i;
12050         r_decalsystem_splatqueue_t *queue;
12051
12052         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12053                 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);
12054         r_decalsystem_numqueued = 0;
12055 }
12056
12057 extern cvar_t cl_decals_max;
12058 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12059 {
12060         int i;
12061         decalsystem_t *decalsystem = &ent->decalsystem;
12062         int numdecals;
12063         unsigned int killsequence;
12064         tridecal_t *decal;
12065         float frametime;
12066         float lifetime;
12067
12068         if (!decalsystem->numdecals)
12069                 return;
12070
12071         if (r_showsurfaces.integer)
12072                 return;
12073
12074         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12075         {
12076                 R_DecalSystem_Reset(decalsystem);
12077                 return;
12078         }
12079
12080         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12081         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12082
12083         if (decalsystem->lastupdatetime)
12084                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12085         else
12086                 frametime = 0;
12087         decalsystem->lastupdatetime = r_refdef.scene.time;
12088         numdecals = decalsystem->numdecals;
12089
12090         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12091         {
12092                 if (decal->color4f[0][3])
12093                 {
12094                         decal->lived += frametime;
12095                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12096                         {
12097                                 memset(decal, 0, sizeof(*decal));
12098                                 if (decalsystem->freedecal > i)
12099                                         decalsystem->freedecal = i;
12100                         }
12101                 }
12102         }
12103         decal = decalsystem->decals;
12104         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12105                 numdecals--;
12106
12107         // collapse the array by shuffling the tail decals into the gaps
12108         for (;;)
12109         {
12110                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12111                         decalsystem->freedecal++;
12112                 if (decalsystem->freedecal == numdecals)
12113                         break;
12114                 decal[decalsystem->freedecal] = decal[--numdecals];
12115         }
12116
12117         decalsystem->numdecals = numdecals;
12118
12119         if (numdecals <= 0)
12120         {
12121                 // if there are no decals left, reset decalsystem
12122                 R_DecalSystem_Reset(decalsystem);
12123         }
12124 }
12125
12126 extern skinframe_t *decalskinframe;
12127 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12128 {
12129         int i;
12130         decalsystem_t *decalsystem = &ent->decalsystem;
12131         int numdecals;
12132         tridecal_t *decal;
12133         float faderate;
12134         float alpha;
12135         float *v3f;
12136         float *c4f;
12137         float *t2f;
12138         const int *e;
12139         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12140         int numtris = 0;
12141
12142         numdecals = decalsystem->numdecals;
12143         if (!numdecals)
12144                 return;
12145
12146         if (r_showsurfaces.integer)
12147                 return;
12148
12149         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12150         {
12151                 R_DecalSystem_Reset(decalsystem);
12152                 return;
12153         }
12154
12155         // if the model is static it doesn't matter what value we give for
12156         // wantnormals and wanttangents, so this logic uses only rules applicable
12157         // to a model, knowing that they are meaningless otherwise
12158         if (ent == r_refdef.scene.worldentity)
12159                 RSurf_ActiveWorldEntity();
12160         else
12161                 RSurf_ActiveModelEntity(ent, false, false, false);
12162
12163         decalsystem->lastupdatetime = r_refdef.scene.time;
12164
12165         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12166
12167         // update vertex positions for animated models
12168         v3f = decalsystem->vertex3f;
12169         c4f = decalsystem->color4f;
12170         t2f = decalsystem->texcoord2f;
12171         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12172         {
12173                 if (!decal->color4f[0][3])
12174                         continue;
12175
12176                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12177                         continue;
12178
12179                 // skip backfaces
12180                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12181                         continue;
12182
12183                 // update color values for fading decals
12184                 if (decal->lived >= cl_decals_time.value)
12185                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12186                 else
12187                         alpha = 1.0f;
12188
12189                 c4f[ 0] = decal->color4f[0][0] * alpha;
12190                 c4f[ 1] = decal->color4f[0][1] * alpha;
12191                 c4f[ 2] = decal->color4f[0][2] * alpha;
12192                 c4f[ 3] = 1;
12193                 c4f[ 4] = decal->color4f[1][0] * alpha;
12194                 c4f[ 5] = decal->color4f[1][1] * alpha;
12195                 c4f[ 6] = decal->color4f[1][2] * alpha;
12196                 c4f[ 7] = 1;
12197                 c4f[ 8] = decal->color4f[2][0] * alpha;
12198                 c4f[ 9] = decal->color4f[2][1] * alpha;
12199                 c4f[10] = decal->color4f[2][2] * alpha;
12200                 c4f[11] = 1;
12201
12202                 t2f[0] = decal->texcoord2f[0][0];
12203                 t2f[1] = decal->texcoord2f[0][1];
12204                 t2f[2] = decal->texcoord2f[1][0];
12205                 t2f[3] = decal->texcoord2f[1][1];
12206                 t2f[4] = decal->texcoord2f[2][0];
12207                 t2f[5] = decal->texcoord2f[2][1];
12208
12209                 // update vertex positions for animated models
12210                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12211                 {
12212                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12213                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12214                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12215                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12216                 }
12217                 else
12218                 {
12219                         VectorCopy(decal->vertex3f[0], v3f);
12220                         VectorCopy(decal->vertex3f[1], v3f + 3);
12221                         VectorCopy(decal->vertex3f[2], v3f + 6);
12222                 }
12223
12224                 if (r_refdef.fogenabled)
12225                 {
12226                         alpha = RSurf_FogVertex(v3f);
12227                         VectorScale(c4f, alpha, c4f);
12228                         alpha = RSurf_FogVertex(v3f + 3);
12229                         VectorScale(c4f + 4, alpha, c4f + 4);
12230                         alpha = RSurf_FogVertex(v3f + 6);
12231                         VectorScale(c4f + 8, alpha, c4f + 8);
12232                 }
12233
12234                 v3f += 9;
12235                 c4f += 12;
12236                 t2f += 6;
12237                 numtris++;
12238         }
12239
12240         if (numtris > 0)
12241         {
12242                 r_refdef.stats[r_stat_drawndecals] += numtris;
12243
12244                 // now render the decals all at once
12245                 // (this assumes they all use one particle font texture!)
12246                 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);
12247 //              R_Mesh_ResetTextureState();
12248                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12249                 GL_DepthMask(false);
12250                 GL_DepthRange(0, 1);
12251                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12252                 GL_DepthTest(true);
12253                 GL_CullFace(GL_NONE);
12254                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12255                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12256                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12257         }
12258 }
12259
12260 static void R_DrawModelDecals(void)
12261 {
12262         int i, numdecals;
12263
12264         // fade faster when there are too many decals
12265         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12266         for (i = 0;i < r_refdef.scene.numentities;i++)
12267                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12268
12269         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12270         for (i = 0;i < r_refdef.scene.numentities;i++)
12271                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12272                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12273
12274         R_DecalSystem_ApplySplatEntitiesQueue();
12275
12276         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12277         for (i = 0;i < r_refdef.scene.numentities;i++)
12278                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12279
12280         r_refdef.stats[r_stat_totaldecals] += numdecals;
12281
12282         if (r_showsurfaces.integer)
12283                 return;
12284
12285         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12286
12287         for (i = 0;i < r_refdef.scene.numentities;i++)
12288         {
12289                 if (!r_refdef.viewcache.entityvisible[i])
12290                         continue;
12291                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12292                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12293         }
12294 }
12295
12296 extern cvar_t mod_collision_bih;
12297 static void R_DrawDebugModel(void)
12298 {
12299         entity_render_t *ent = rsurface.entity;
12300         int i, j, flagsmask;
12301         const msurface_t *surface;
12302         dp_model_t *model = ent->model;
12303
12304         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12305                 return;
12306
12307         if (r_showoverdraw.value > 0)
12308         {
12309                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12310                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12311                 R_SetupShader_Generic_NoTexture(false, false);
12312                 GL_DepthTest(false);
12313                 GL_DepthMask(false);
12314                 GL_DepthRange(0, 1);
12315                 GL_BlendFunc(GL_ONE, GL_ONE);
12316                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12317                 {
12318                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12319                                 continue;
12320                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12321                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12322                         {
12323                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12324                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12325                                 if (!rsurface.texture->currentlayers->depthmask)
12326                                         GL_Color(c, 0, 0, 1.0f);
12327                                 else if (ent == r_refdef.scene.worldentity)
12328                                         GL_Color(c, c, c, 1.0f);
12329                                 else
12330                                         GL_Color(0, c, 0, 1.0f);
12331                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12332                                 RSurf_DrawBatch();
12333                         }
12334                 }
12335                 rsurface.texture = NULL;
12336         }
12337
12338         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12339
12340 //      R_Mesh_ResetTextureState();
12341         R_SetupShader_Generic_NoTexture(false, false);
12342         GL_DepthRange(0, 1);
12343         GL_DepthTest(!r_showdisabledepthtest.integer);
12344         GL_DepthMask(false);
12345         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12346
12347         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12348         {
12349                 int triangleindex;
12350                 int bihleafindex;
12351                 qboolean cullbox = false;
12352                 const q3mbrush_t *brush;
12353                 const bih_t *bih = &model->collision_bih;
12354                 const bih_leaf_t *bihleaf;
12355                 float vertex3f[3][3];
12356                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12357                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12358                 {
12359                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12360                                 continue;
12361                         switch (bihleaf->type)
12362                         {
12363                         case BIH_BRUSH:
12364                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12365                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12366                                 {
12367                                         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);
12368                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12369                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12370                                 }
12371                                 break;
12372                         case BIH_COLLISIONTRIANGLE:
12373                                 triangleindex = bihleaf->itemindex;
12374                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12375                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12376                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12377                                 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);
12378                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12379                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12380                                 break;
12381                         case BIH_RENDERTRIANGLE:
12382                                 triangleindex = bihleaf->itemindex;
12383                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12384                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12385                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12386                                 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);
12387                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12388                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12389                                 break;
12390                         }
12391                 }
12392         }
12393
12394         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12395
12396 #ifndef USE_GLES2
12397         if (r_showtris.integer && qglPolygonMode)
12398         {
12399                 if (r_showdisabledepthtest.integer)
12400                 {
12401                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12402                         GL_DepthMask(false);
12403                 }
12404                 else
12405                 {
12406                         GL_BlendFunc(GL_ONE, GL_ZERO);
12407                         GL_DepthMask(true);
12408                 }
12409                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12410                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12411                 {
12412                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12413                                 continue;
12414                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12415                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12416                         {
12417                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12418                                 if (!rsurface.texture->currentlayers->depthmask)
12419                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12420                                 else if (ent == r_refdef.scene.worldentity)
12421                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12422                                 else
12423                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12424                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12425                                 RSurf_DrawBatch();
12426                         }
12427                 }
12428                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12429                 rsurface.texture = NULL;
12430         }
12431
12432         if (r_shownormals.value != 0 && qglBegin)
12433         {
12434                 int l, k;
12435                 vec3_t v;
12436                 if (r_showdisabledepthtest.integer)
12437                 {
12438                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12439                         GL_DepthMask(false);
12440                 }
12441                 else
12442                 {
12443                         GL_BlendFunc(GL_ONE, GL_ZERO);
12444                         GL_DepthMask(true);
12445                 }
12446                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12447                 {
12448                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12449                                 continue;
12450                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12451                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12452                         {
12453                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12454                                 qglBegin(GL_LINES);
12455                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12456                                 {
12457                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12458                                         {
12459                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12460                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12461                                                 qglVertex3f(v[0], v[1], v[2]);
12462                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12463                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12464                                                 qglVertex3f(v[0], v[1], v[2]);
12465                                         }
12466                                 }
12467                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12468                                 {
12469                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12470                                         {
12471                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12472                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12473                                                 qglVertex3f(v[0], v[1], v[2]);
12474                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12475                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12476                                                 qglVertex3f(v[0], v[1], v[2]);
12477                                         }
12478                                 }
12479                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12480                                 {
12481                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12482                                         {
12483                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12484                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12485                                                 qglVertex3f(v[0], v[1], v[2]);
12486                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12487                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12488                                                 qglVertex3f(v[0], v[1], v[2]);
12489                                         }
12490                                 }
12491                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12492                                 {
12493                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12494                                         {
12495                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12496                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12497                                                 qglVertex3f(v[0], v[1], v[2]);
12498                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12499                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12500                                                 qglVertex3f(v[0], v[1], v[2]);
12501                                         }
12502                                 }
12503                                 qglEnd();
12504                                 CHECKGLERROR
12505                         }
12506                 }
12507                 rsurface.texture = NULL;
12508         }
12509 #endif
12510 }
12511
12512 int r_maxsurfacelist = 0;
12513 const msurface_t **r_surfacelist = NULL;
12514 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12515 {
12516         int i, j, endj, flagsmask;
12517         dp_model_t *model = r_refdef.scene.worldmodel;
12518         msurface_t *surfaces;
12519         unsigned char *update;
12520         int numsurfacelist = 0;
12521         if (model == NULL)
12522                 return;
12523
12524         if (r_maxsurfacelist < model->num_surfaces)
12525         {
12526                 r_maxsurfacelist = model->num_surfaces;
12527                 if (r_surfacelist)
12528                         Mem_Free((msurface_t**)r_surfacelist);
12529                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12530         }
12531
12532         RSurf_ActiveWorldEntity();
12533
12534         surfaces = model->data_surfaces;
12535         update = model->brushq1.lightmapupdateflags;
12536
12537         // update light styles on this submodel
12538         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12539         {
12540                 model_brush_lightstyleinfo_t *style;
12541                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12542                 {
12543                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12544                         {
12545                                 int *list = style->surfacelist;
12546                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12547                                 for (j = 0;j < style->numsurfaces;j++)
12548                                         update[list[j]] = true;
12549                         }
12550                 }
12551         }
12552
12553         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12554
12555         if (debug)
12556         {
12557                 R_DrawDebugModel();
12558                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12559                 return;
12560         }
12561
12562         rsurface.lightmaptexture = NULL;
12563         rsurface.deluxemaptexture = NULL;
12564         rsurface.uselightmaptexture = false;
12565         rsurface.texture = NULL;
12566         rsurface.rtlight = NULL;
12567         numsurfacelist = 0;
12568         // add visible surfaces to draw list
12569         for (i = 0;i < model->nummodelsurfaces;i++)
12570         {
12571                 j = model->sortedmodelsurfaces[i];
12572                 if (r_refdef.viewcache.world_surfacevisible[j])
12573                         r_surfacelist[numsurfacelist++] = surfaces + j;
12574         }
12575         // update lightmaps if needed
12576         if (model->brushq1.firstrender)
12577         {
12578                 model->brushq1.firstrender = false;
12579                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12580                         if (update[j])
12581                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12582         }
12583         else if (update)
12584         {
12585                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12586                         if (r_refdef.viewcache.world_surfacevisible[j])
12587                                 if (update[j])
12588                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12589         }
12590         // don't do anything if there were no surfaces
12591         if (!numsurfacelist)
12592         {
12593                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12594                 return;
12595         }
12596         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12597
12598         // add to stats if desired
12599         if (r_speeds.integer && !skysurfaces && !depthonly)
12600         {
12601                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12602                 for (j = 0;j < numsurfacelist;j++)
12603                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12604         }
12605
12606         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12607 }
12608
12609 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12610 {
12611         int i, j, endj, flagsmask;
12612         dp_model_t *model = ent->model;
12613         msurface_t *surfaces;
12614         unsigned char *update;
12615         int numsurfacelist = 0;
12616         if (model == NULL)
12617                 return;
12618
12619         if (r_maxsurfacelist < model->num_surfaces)
12620         {
12621                 r_maxsurfacelist = model->num_surfaces;
12622                 if (r_surfacelist)
12623                         Mem_Free((msurface_t **)r_surfacelist);
12624                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12625         }
12626
12627         // if the model is static it doesn't matter what value we give for
12628         // wantnormals and wanttangents, so this logic uses only rules applicable
12629         // to a model, knowing that they are meaningless otherwise
12630         if (ent == r_refdef.scene.worldentity)
12631                 RSurf_ActiveWorldEntity();
12632         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12633                 RSurf_ActiveModelEntity(ent, false, false, false);
12634         else if (prepass)
12635                 RSurf_ActiveModelEntity(ent, true, true, true);
12636         else if (depthonly)
12637         {
12638                 switch (vid.renderpath)
12639                 {
12640                 case RENDERPATH_GL20:
12641                 case RENDERPATH_D3D9:
12642                 case RENDERPATH_D3D10:
12643                 case RENDERPATH_D3D11:
12644                 case RENDERPATH_SOFT:
12645                 case RENDERPATH_GLES2:
12646                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12647                         break;
12648                 case RENDERPATH_GL11:
12649                 case RENDERPATH_GL13:
12650                 case RENDERPATH_GLES1:
12651                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12652                         break;
12653                 }
12654         }
12655         else
12656         {
12657                 switch (vid.renderpath)
12658                 {
12659                 case RENDERPATH_GL20:
12660                 case RENDERPATH_D3D9:
12661                 case RENDERPATH_D3D10:
12662                 case RENDERPATH_D3D11:
12663                 case RENDERPATH_SOFT:
12664                 case RENDERPATH_GLES2:
12665                         RSurf_ActiveModelEntity(ent, true, true, false);
12666                         break;
12667                 case RENDERPATH_GL11:
12668                 case RENDERPATH_GL13:
12669                 case RENDERPATH_GLES1:
12670                         RSurf_ActiveModelEntity(ent, true, false, false);
12671                         break;
12672                 }
12673         }
12674
12675         surfaces = model->data_surfaces;
12676         update = model->brushq1.lightmapupdateflags;
12677
12678         // update light styles
12679         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12680         {
12681                 model_brush_lightstyleinfo_t *style;
12682                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12683                 {
12684                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12685                         {
12686                                 int *list = style->surfacelist;
12687                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12688                                 for (j = 0;j < style->numsurfaces;j++)
12689                                         update[list[j]] = true;
12690                         }
12691                 }
12692         }
12693
12694         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12695
12696         if (debug)
12697         {
12698                 R_DrawDebugModel();
12699                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12700                 return;
12701         }
12702
12703         rsurface.lightmaptexture = NULL;
12704         rsurface.deluxemaptexture = NULL;
12705         rsurface.uselightmaptexture = false;
12706         rsurface.texture = NULL;
12707         rsurface.rtlight = NULL;
12708         numsurfacelist = 0;
12709         // add visible surfaces to draw list
12710         for (i = 0;i < model->nummodelsurfaces;i++)
12711                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12712         // don't do anything if there were no surfaces
12713         if (!numsurfacelist)
12714         {
12715                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12716                 return;
12717         }
12718         // update lightmaps if needed
12719         if (update)
12720         {
12721                 int updated = 0;
12722                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12723                 {
12724                         if (update[j])
12725                         {
12726                                 updated++;
12727                                 R_BuildLightMap(ent, surfaces + j);
12728                         }
12729                 }
12730         }
12731
12732         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12733
12734         // add to stats if desired
12735         if (r_speeds.integer && !skysurfaces && !depthonly)
12736         {
12737                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12738                 for (j = 0;j < numsurfacelist;j++)
12739                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12740         }
12741
12742         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12743 }
12744
12745 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12746 {
12747         static texture_t texture;
12748         static msurface_t surface;
12749         const msurface_t *surfacelist = &surface;
12750
12751         // fake enough texture and surface state to render this geometry
12752
12753         texture.update_lastrenderframe = -1; // regenerate this texture
12754         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12755         texture.basealpha = 1.0f;
12756         texture.currentskinframe = skinframe;
12757         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12758         texture.offsetmapping = OFFSETMAPPING_OFF;
12759         texture.offsetscale = 1;
12760         texture.specularscalemod = 1;
12761         texture.specularpowermod = 1;
12762         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12763         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12764         // JUST GREP FOR "specularscalemod = 1".
12765
12766         surface.texture = &texture;
12767         surface.num_triangles = numtriangles;
12768         surface.num_firsttriangle = firsttriangle;
12769         surface.num_vertices = numvertices;
12770         surface.num_firstvertex = firstvertex;
12771
12772         // now render it
12773         rsurface.texture = R_GetCurrentTexture(surface.texture);
12774         rsurface.lightmaptexture = NULL;
12775         rsurface.deluxemaptexture = NULL;
12776         rsurface.uselightmaptexture = false;
12777         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12778 }
12779
12780 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)
12781 {
12782         static msurface_t surface;
12783         const msurface_t *surfacelist = &surface;
12784
12785         // fake enough texture and surface state to render this geometry
12786         surface.texture = texture;
12787         surface.num_triangles = numtriangles;
12788         surface.num_firsttriangle = firsttriangle;
12789         surface.num_vertices = numvertices;
12790         surface.num_firstvertex = firstvertex;
12791
12792         // now render it
12793         rsurface.texture = R_GetCurrentTexture(surface.texture);
12794         rsurface.lightmaptexture = NULL;
12795         rsurface.deluxemaptexture = NULL;
12796         rsurface.uselightmaptexture = false;
12797         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12798 }