]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Refactored R_UpdateEntityLighting to CL_UpdateEntityShading, which sets fields like...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31 #include "cl_collision.h"
32
33 #ifdef SUPPORTD3D
34 #include <d3d9.h>
35 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
36 #endif
37
38 #ifdef WIN32
39 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
44 #ifdef __cplusplus
45 }
46 #endif
47 #endif
48
49 mempool_t *r_main_mempool;
50 rtexturepool_t *r_main_texturepool;
51
52 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53
54 static qboolean r_loadnormalmap;
55 static qboolean r_loadgloss;
56 qboolean r_loadfog;
57 static qboolean r_loaddds;
58 static qboolean r_savedds;
59 static qboolean r_gpuskeletal;
60
61 //
62 // screen size info
63 //
64 r_refdef_t r_refdef;
65
66 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
68 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
69 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
70 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
71 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
72 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
73 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
74 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
75 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
76 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
77 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
78
79 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
80 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
82 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
84
85 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
86 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
87 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
88 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
89 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
90 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
91 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
92 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
93 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
94 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
95 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
96 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
97 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%,  10 = 100%)" };
98 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)"};
99 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
100 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
101 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"};
102 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"};
103 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
104 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"};
105 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"};
106 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"};
107 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
108 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
109 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
110 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
111 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
112 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
113 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
114 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
115 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)"};
116 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)"};
117 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
118 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
119 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
120 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
121 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
122 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
123
124 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
125 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
126 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
127
128 cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"};
129 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
130 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
131 cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"};
132 cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"};
133
134 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
135 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
136 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
137 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."};
138 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
139 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
140 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
141 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."};
142 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
143 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
144 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
145 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."};
146 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
147 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"};
148 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"};
149 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
151 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
152 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
153 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
154 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"};
155 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
156 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
157 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
158 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
159 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
160
161 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
162 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
163 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
164 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
165 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
166 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
167 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
168 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
169
170 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)"};
171 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"};
172
173 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
174 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
175 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
176
177 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"};
178 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"};
179 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"};
180 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
181 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
182 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"};
183 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)"};
184 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)"};
185 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
186
187 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
188 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)"};
189 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
190 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)"};
191 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
192 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)"};
193 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)"};
194 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
195 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"};
196 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."};
197 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
198 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)"};
199 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)"};
200 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)"};
201 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)"};
202 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)"};
203 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)"};
204 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)"};
205 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)"};
206
207 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)"};
208 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)"};
209 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
210 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"};
211 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
212 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
213 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
214 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"};
215 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"};
216 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)"};
217
218 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
219 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
220 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
221 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
222
223 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
224 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
225
226 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
227 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
228 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
229 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
230 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
231 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
232
233 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
234 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
235 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
236 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
237 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
239 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
240 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
241 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
242 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
243
244 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"};
245
246 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"};
247
248 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
249
250 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
251
252 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)"};
253 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)"};
254 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
255 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
256
257 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
258 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"};
259
260 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."};
261
262 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)"};
263 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
264 {
265         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
266         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
267         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
268         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
269 };
270
271 extern cvar_t v_glslgamma;
272 extern cvar_t v_glslgamma_2d;
273
274 extern qboolean v_flipped_state;
275
276 r_framebufferstate_t r_fb;
277
278 /// shadow volume bsp struct with automatically growing nodes buffer
279 svbsp_t r_svbsp;
280
281 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
282
283 rtexture_t *r_texture_blanknormalmap;
284 rtexture_t *r_texture_white;
285 rtexture_t *r_texture_grey128;
286 rtexture_t *r_texture_black;
287 rtexture_t *r_texture_notexture;
288 rtexture_t *r_texture_whitecube;
289 rtexture_t *r_texture_normalizationcube;
290 rtexture_t *r_texture_fogattenuation;
291 rtexture_t *r_texture_fogheighttexture;
292 rtexture_t *r_texture_gammaramps;
293 unsigned int r_texture_gammaramps_serial;
294 //rtexture_t *r_texture_fogintensity;
295 rtexture_t *r_texture_reflectcube;
296
297 // TODO: hash lookups?
298 typedef struct cubemapinfo_s
299 {
300         char basename[64];
301         rtexture_t *texture;
302 }
303 cubemapinfo_t;
304
305 int r_texture_numcubemaps;
306 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
307
308 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
309 unsigned int r_numqueries;
310 unsigned int r_maxqueries;
311
312 typedef struct r_qwskincache_s
313 {
314         char name[MAX_QPATH];
315         skinframe_t *skinframe;
316 }
317 r_qwskincache_t;
318
319 static r_qwskincache_t *r_qwskincache;
320 static int r_qwskincache_size;
321
322 /// vertex coordinates for a quad that covers the screen exactly
323 extern const float r_screenvertex3f[12];
324 extern const float r_d3dscreenvertex3f[12];
325 const float r_screenvertex3f[12] =
326 {
327         0, 0, 0,
328         1, 0, 0,
329         1, 1, 0,
330         0, 1, 0
331 };
332 const float r_d3dscreenvertex3f[12] =
333 {
334         0, 1, 0,
335         1, 1, 0,
336         1, 0, 0,
337         0, 0, 0
338 };
339
340 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
341 {
342         int i;
343         for (i = 0;i < verts;i++)
344         {
345                 out[0] = in[0] * r;
346                 out[1] = in[1] * g;
347                 out[2] = in[2] * b;
348                 out[3] = in[3];
349                 in += 4;
350                 out += 4;
351         }
352 }
353
354 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
355 {
356         int i;
357         for (i = 0;i < verts;i++)
358         {
359                 out[0] = r;
360                 out[1] = g;
361                 out[2] = b;
362                 out[3] = a;
363                 out += 4;
364         }
365 }
366
367 // FIXME: move this to client?
368 void FOG_clear(void)
369 {
370         if (gamemode == GAME_NEHAHRA)
371         {
372                 Cvar_Set("gl_fogenable", "0");
373                 Cvar_Set("gl_fogdensity", "0.2");
374                 Cvar_Set("gl_fogred", "0.3");
375                 Cvar_Set("gl_foggreen", "0.3");
376                 Cvar_Set("gl_fogblue", "0.3");
377         }
378         r_refdef.fog_density = 0;
379         r_refdef.fog_red = 0;
380         r_refdef.fog_green = 0;
381         r_refdef.fog_blue = 0;
382         r_refdef.fog_alpha = 1;
383         r_refdef.fog_start = 0;
384         r_refdef.fog_end = 16384;
385         r_refdef.fog_height = 1<<30;
386         r_refdef.fog_fadedepth = 128;
387         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
388 }
389
390 static void R_BuildBlankTextures(void)
391 {
392         unsigned char data[4];
393         data[2] = 128; // normal X
394         data[1] = 128; // normal Y
395         data[0] = 255; // normal Z
396         data[3] = 255; // height
397         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
398         data[0] = 255;
399         data[1] = 255;
400         data[2] = 255;
401         data[3] = 255;
402         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
403         data[0] = 128;
404         data[1] = 128;
405         data[2] = 128;
406         data[3] = 255;
407         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
408         data[0] = 0;
409         data[1] = 0;
410         data[2] = 0;
411         data[3] = 255;
412         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
413 }
414
415 static void R_BuildNoTexture(void)
416 {
417         int x, y;
418         unsigned char pix[16][16][4];
419         // this makes a light grey/dark grey checkerboard texture
420         for (y = 0;y < 16;y++)
421         {
422                 for (x = 0;x < 16;x++)
423                 {
424                         if ((y < 8) ^ (x < 8))
425                         {
426                                 pix[y][x][0] = 128;
427                                 pix[y][x][1] = 128;
428                                 pix[y][x][2] = 128;
429                                 pix[y][x][3] = 255;
430                         }
431                         else
432                         {
433                                 pix[y][x][0] = 64;
434                                 pix[y][x][1] = 64;
435                                 pix[y][x][2] = 64;
436                                 pix[y][x][3] = 255;
437                         }
438                 }
439         }
440         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
441 }
442
443 static void R_BuildWhiteCube(void)
444 {
445         unsigned char data[6*1*1*4];
446         memset(data, 255, sizeof(data));
447         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
448 }
449
450 static void R_BuildNormalizationCube(void)
451 {
452         int x, y, side;
453         vec3_t v;
454         vec_t s, t, intensity;
455 #define NORMSIZE 64
456         unsigned char *data;
457         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
458         for (side = 0;side < 6;side++)
459         {
460                 for (y = 0;y < NORMSIZE;y++)
461                 {
462                         for (x = 0;x < NORMSIZE;x++)
463                         {
464                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
465                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
466                                 switch(side)
467                                 {
468                                 default:
469                                 case 0:
470                                         v[0] = 1;
471                                         v[1] = -t;
472                                         v[2] = -s;
473                                         break;
474                                 case 1:
475                                         v[0] = -1;
476                                         v[1] = -t;
477                                         v[2] = s;
478                                         break;
479                                 case 2:
480                                         v[0] = s;
481                                         v[1] = 1;
482                                         v[2] = t;
483                                         break;
484                                 case 3:
485                                         v[0] = s;
486                                         v[1] = -1;
487                                         v[2] = -t;
488                                         break;
489                                 case 4:
490                                         v[0] = s;
491                                         v[1] = -t;
492                                         v[2] = 1;
493                                         break;
494                                 case 5:
495                                         v[0] = -s;
496                                         v[1] = -t;
497                                         v[2] = -1;
498                                         break;
499                                 }
500                                 intensity = 127.0f / sqrt(DotProduct(v, v));
501                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
502                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
503                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
504                                 data[((side*64+y)*64+x)*4+3] = 255;
505                         }
506                 }
507         }
508         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
509         Mem_Free(data);
510 }
511
512 static void R_BuildFogTexture(void)
513 {
514         int x, b;
515 #define FOGWIDTH 256
516         unsigned char data1[FOGWIDTH][4];
517         //unsigned char data2[FOGWIDTH][4];
518         double d, r, alpha;
519
520         r_refdef.fogmasktable_start = r_refdef.fog_start;
521         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
522         r_refdef.fogmasktable_range = r_refdef.fogrange;
523         r_refdef.fogmasktable_density = r_refdef.fog_density;
524
525         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
526         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
527         {
528                 d = (x * r - r_refdef.fogmasktable_start);
529                 if(developer_extra.integer)
530                         Con_DPrintf("%f ", d);
531                 d = max(0, d);
532                 if (r_fog_exp2.integer)
533                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
534                 else
535                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
536                 if(developer_extra.integer)
537                         Con_DPrintf(" : %f ", alpha);
538                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
539                 if(developer_extra.integer)
540                         Con_DPrintf(" = %f\n", alpha);
541                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
542         }
543
544         for (x = 0;x < FOGWIDTH;x++)
545         {
546                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
547                 data1[x][0] = b;
548                 data1[x][1] = b;
549                 data1[x][2] = b;
550                 data1[x][3] = 255;
551                 //data2[x][0] = 255 - b;
552                 //data2[x][1] = 255 - b;
553                 //data2[x][2] = 255 - b;
554                 //data2[x][3] = 255;
555         }
556         if (r_texture_fogattenuation)
557         {
558                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
559                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
560         }
561         else
562         {
563                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
564                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
565         }
566 }
567
568 static void R_BuildFogHeightTexture(void)
569 {
570         unsigned char *inpixels;
571         int size;
572         int x;
573         int y;
574         int j;
575         float c[4];
576         float f;
577         inpixels = NULL;
578         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
579         if (r_refdef.fogheighttexturename[0])
580                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
581         if (!inpixels)
582         {
583                 r_refdef.fog_height_tablesize = 0;
584                 if (r_texture_fogheighttexture)
585                         R_FreeTexture(r_texture_fogheighttexture);
586                 r_texture_fogheighttexture = NULL;
587                 if (r_refdef.fog_height_table2d)
588                         Mem_Free(r_refdef.fog_height_table2d);
589                 r_refdef.fog_height_table2d = NULL;
590                 if (r_refdef.fog_height_table1d)
591                         Mem_Free(r_refdef.fog_height_table1d);
592                 r_refdef.fog_height_table1d = NULL;
593                 return;
594         }
595         size = image_width;
596         r_refdef.fog_height_tablesize = size;
597         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
598         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
599         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
600         Mem_Free(inpixels);
601         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
602         // average fog color table accounting for every fog layer between a point
603         // and the camera.  (Note: attenuation is handled separately!)
604         for (y = 0;y < size;y++)
605         {
606                 for (x = 0;x < size;x++)
607                 {
608                         Vector4Clear(c);
609                         f = 0;
610                         if (x < y)
611                         {
612                                 for (j = x;j <= y;j++)
613                                 {
614                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
615                                         f++;
616                                 }
617                         }
618                         else
619                         {
620                                 for (j = x;j >= y;j--)
621                                 {
622                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
623                                         f++;
624                                 }
625                         }
626                         f = 1.0f / f;
627                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
628                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
629                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
630                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
631                 }
632         }
633         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
634 }
635
636 //=======================================================================================================================================================
637
638 static const char *builtinshaderstrings[] =
639 {
640 #include "shader_glsl.h"
641 0
642 };
643
644 const char *builtinhlslshaderstrings[] =
645 {
646 #include "shader_hlsl.h"
647 0
648 };
649
650 //=======================================================================================================================================================
651
652 typedef struct shaderpermutationinfo_s
653 {
654         const char *pretext;
655         const char *name;
656 }
657 shaderpermutationinfo_t;
658
659 typedef struct shadermodeinfo_s
660 {
661         const char *sourcebasename;
662         const char *extension;
663         const char **builtinshaderstrings;
664         const char *pretext;
665         const char *name;
666         char *filename;
667         char *builtinstring;
668         int builtincrc;
669 }
670 shadermodeinfo_t;
671
672 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
673 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
674 {
675         {"#define USEDIFFUSE\n", " diffuse"},
676         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
677         {"#define USEVIEWTINT\n", " viewtint"},
678         {"#define USECOLORMAPPING\n", " colormapping"},
679         {"#define USESATURATION\n", " saturation"},
680         {"#define USEFOGINSIDE\n", " foginside"},
681         {"#define USEFOGOUTSIDE\n", " fogoutside"},
682         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
683         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
684         {"#define USEGAMMARAMPS\n", " gammaramps"},
685         {"#define USECUBEFILTER\n", " cubefilter"},
686         {"#define USEGLOW\n", " glow"},
687         {"#define USEBLOOM\n", " bloom"},
688         {"#define USESPECULAR\n", " specular"},
689         {"#define USEPOSTPROCESSING\n", " postprocessing"},
690         {"#define USEREFLECTION\n", " reflection"},
691         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
692         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
693         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
694         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
695         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
696         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
697         {"#define USEALPHAKILL\n", " alphakill"},
698         {"#define USEREFLECTCUBE\n", " reflectcube"},
699         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
700         {"#define USEBOUNCEGRID\n", " bouncegrid"},
701         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
702         {"#define USETRIPPY\n", " trippy"},
703         {"#define USEDEPTHRGB\n", " depthrgb"},
704         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
705         {"#define USESKELETAL\n", " skeletal"},
706         {"#define USEOCCLUDE\n", " occlude"}
707 };
708
709 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
710 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
711 {
712         // SHADERLANGUAGE_GLSL
713         {
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
723                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
724                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
725                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
726                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
727                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
728                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
729                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
730                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
731         },
732         // SHADERLANGUAGE_HLSL
733         {
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
743                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
744                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
745                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
746                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
747                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
748                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
749                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
750                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
751         },
752 };
753
754 struct r_glsl_permutation_s;
755 typedef struct r_glsl_permutation_s
756 {
757         /// hash lookup data
758         struct r_glsl_permutation_s *hashnext;
759         unsigned int mode;
760         dpuint64 permutation;
761
762         /// indicates if we have tried compiling this permutation already
763         qboolean compiled;
764         /// 0 if compilation failed
765         int program;
766         // texture units assigned to each detected uniform
767         int tex_Texture_First;
768         int tex_Texture_Second;
769         int tex_Texture_GammaRamps;
770         int tex_Texture_Normal;
771         int tex_Texture_Color;
772         int tex_Texture_Gloss;
773         int tex_Texture_Glow;
774         int tex_Texture_SecondaryNormal;
775         int tex_Texture_SecondaryColor;
776         int tex_Texture_SecondaryGloss;
777         int tex_Texture_SecondaryGlow;
778         int tex_Texture_Pants;
779         int tex_Texture_Shirt;
780         int tex_Texture_FogHeightTexture;
781         int tex_Texture_FogMask;
782         int tex_Texture_Lightmap;
783         int tex_Texture_Deluxemap;
784         int tex_Texture_Attenuation;
785         int tex_Texture_Cube;
786         int tex_Texture_Refraction;
787         int tex_Texture_Reflection;
788         int tex_Texture_ShadowMap2D;
789         int tex_Texture_CubeProjection;
790         int tex_Texture_ScreenNormalMap;
791         int tex_Texture_ScreenDiffuse;
792         int tex_Texture_ScreenSpecular;
793         int tex_Texture_ReflectMask;
794         int tex_Texture_ReflectCube;
795         int tex_Texture_BounceGrid;
796         /// locations of detected uniforms in program object, or -1 if not found
797         int loc_Texture_First;
798         int loc_Texture_Second;
799         int loc_Texture_GammaRamps;
800         int loc_Texture_Normal;
801         int loc_Texture_Color;
802         int loc_Texture_Gloss;
803         int loc_Texture_Glow;
804         int loc_Texture_SecondaryNormal;
805         int loc_Texture_SecondaryColor;
806         int loc_Texture_SecondaryGloss;
807         int loc_Texture_SecondaryGlow;
808         int loc_Texture_Pants;
809         int loc_Texture_Shirt;
810         int loc_Texture_FogHeightTexture;
811         int loc_Texture_FogMask;
812         int loc_Texture_Lightmap;
813         int loc_Texture_Deluxemap;
814         int loc_Texture_Attenuation;
815         int loc_Texture_Cube;
816         int loc_Texture_Refraction;
817         int loc_Texture_Reflection;
818         int loc_Texture_ShadowMap2D;
819         int loc_Texture_CubeProjection;
820         int loc_Texture_ScreenNormalMap;
821         int loc_Texture_ScreenDiffuse;
822         int loc_Texture_ScreenSpecular;
823         int loc_Texture_ReflectMask;
824         int loc_Texture_ReflectCube;
825         int loc_Texture_BounceGrid;
826         int loc_Alpha;
827         int loc_BloomBlur_Parameters;
828         int loc_ClientTime;
829         int loc_Color_Ambient;
830         int loc_Color_Diffuse;
831         int loc_Color_Specular;
832         int loc_Color_Glow;
833         int loc_Color_Pants;
834         int loc_Color_Shirt;
835         int loc_DeferredColor_Ambient;
836         int loc_DeferredColor_Diffuse;
837         int loc_DeferredColor_Specular;
838         int loc_DeferredMod_Diffuse;
839         int loc_DeferredMod_Specular;
840         int loc_DistortScaleRefractReflect;
841         int loc_EyePosition;
842         int loc_FogColor;
843         int loc_FogHeightFade;
844         int loc_FogPlane;
845         int loc_FogPlaneViewDist;
846         int loc_FogRangeRecip;
847         int loc_LightColor;
848         int loc_LightDir;
849         int loc_LightPosition;
850         int loc_OffsetMapping_ScaleSteps;
851         int loc_OffsetMapping_LodDistance;
852         int loc_OffsetMapping_Bias;
853         int loc_PixelSize;
854         int loc_ReflectColor;
855         int loc_ReflectFactor;
856         int loc_ReflectOffset;
857         int loc_RefractColor;
858         int loc_Saturation;
859         int loc_ScreenCenterRefractReflect;
860         int loc_ScreenScaleRefractReflect;
861         int loc_ScreenToDepth;
862         int loc_ShadowMap_Parameters;
863         int loc_ShadowMap_TextureScale;
864         int loc_SpecularPower;
865         int loc_Skeletal_Transform12;
866         int loc_UserVec1;
867         int loc_UserVec2;
868         int loc_UserVec3;
869         int loc_UserVec4;
870         int loc_ViewTintColor;
871         int loc_ViewToLight;
872         int loc_ModelToLight;
873         int loc_TexMatrix;
874         int loc_BackgroundTexMatrix;
875         int loc_ModelViewProjectionMatrix;
876         int loc_ModelViewMatrix;
877         int loc_PixelToScreenTexCoord;
878         int loc_ModelToReflectCube;
879         int loc_ShadowMapMatrix;
880         int loc_BloomColorSubtract;
881         int loc_NormalmapScrollBlend;
882         int loc_BounceGridMatrix;
883         int loc_BounceGridIntensity;
884         /// uniform block bindings
885         int ubibind_Skeletal_Transform12_UniformBlock;
886         /// uniform block indices
887         int ubiloc_Skeletal_Transform12_UniformBlock;
888 }
889 r_glsl_permutation_t;
890
891 #define SHADERPERMUTATION_HASHSIZE 256
892
893
894 // non-degradable "lightweight" shader parameters to keep the permutations simpler
895 // these can NOT degrade! only use for simple stuff
896 enum
897 {
898         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
899         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
900         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
901         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
902         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
903         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
904         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
905         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
906         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
907         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
908         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
909         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
910         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
911         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
912 };
913 #define SHADERSTATICPARMS_COUNT 14
914
915 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
916 static int shaderstaticparms_count = 0;
917
918 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
919 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
920
921 extern qboolean r_shadow_shadowmapsampler;
922 extern int r_shadow_shadowmappcf;
923 qboolean R_CompileShader_CheckStaticParms(void)
924 {
925         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
926         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
927         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
928
929         // detect all
930         if (r_glsl_saturation_redcompensate.integer)
931                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
932         if (r_glsl_vertextextureblend_usebothalphas.integer)
933                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
934         if (r_shadow_glossexact.integer)
935                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
936         if (r_glsl_postprocess.integer)
937         {
938                 if (r_glsl_postprocess_uservec1_enable.integer)
939                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
940                 if (r_glsl_postprocess_uservec2_enable.integer)
941                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
942                 if (r_glsl_postprocess_uservec3_enable.integer)
943                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
944                 if (r_glsl_postprocess_uservec4_enable.integer)
945                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
946         }
947         if (r_fxaa.integer)
948                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
949         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
950                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
951
952         if (r_shadow_shadowmapsampler)
953                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
954         if (r_shadow_shadowmappcf > 1)
955                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
956         else if (r_shadow_shadowmappcf)
957                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
958         if (r_celshading.integer)
959                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
960         if (r_celoutlines.integer)
961                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
962
963         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
964 }
965
966 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
967         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
968                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
969         else \
970                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
971 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
972 {
973         shaderstaticparms_count = 0;
974
975         // emit all
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
982         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
983         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
984         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
985         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
986         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
987         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
988         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
989         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
990 }
991
992 /// information about each possible shader permutation
993 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
994 /// currently selected permutation
995 r_glsl_permutation_t *r_glsl_permutation;
996 /// storage for permutations linked in the hash table
997 memexpandablearray_t r_glsl_permutationarray;
998
999 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1000 {
1001         //unsigned int hashdepth = 0;
1002         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1003         r_glsl_permutation_t *p;
1004         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1005         {
1006                 if (p->mode == mode && p->permutation == permutation)
1007                 {
1008                         //if (hashdepth > 10)
1009                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1010                         return p;
1011                 }
1012                 //hashdepth++;
1013         }
1014         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1015         p->mode = mode;
1016         p->permutation = permutation;
1017         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1018         r_glsl_permutationhash[mode][hashindex] = p;
1019         //if (hashdepth > 10)
1020         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1021         return p;
1022 }
1023
1024 static char *R_ShaderStrCat(const char **strings)
1025 {
1026         char *string, *s;
1027         const char **p = strings;
1028         const char *t;
1029         size_t len = 0;
1030         for (p = strings;(t = *p);p++)
1031                 len += strlen(t);
1032         len++;
1033         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1034         len = 0;
1035         for (p = strings;(t = *p);p++)
1036         {
1037                 len = strlen(t);
1038                 memcpy(s, t, len);
1039                 s += len;
1040         }
1041         *s = 0;
1042         return string;
1043 }
1044
1045 static char *R_ShaderStrCat(const char **strings);
1046 static void R_InitShaderModeInfo(void)
1047 {
1048         int i, language;
1049         shadermodeinfo_t *modeinfo;
1050         // we have a bunch of things to compute that weren't calculated at engine compile time - all filenames should have a crc of the builtin strings to prevent accidental overrides (any customization must be updated to match engine)
1051         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1052         {
1053                 for (i = 0; i < SHADERMODE_COUNT; i++)
1054                 {
1055                         char filename[MAX_QPATH];
1056                         modeinfo = &shadermodeinfo[language][i];
1057                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1058                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1059                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1060                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1061                 }
1062         }
1063 }
1064
1065 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1066 {
1067         char *shaderstring;
1068         // if the mode has no filename we have to return the builtin string
1069         if (builtinonly || !modeinfo->filename)
1070                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1071         // note that FS_LoadFile appends a 0 byte to make it a valid string
1072         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1073         if (shaderstring)
1074         {
1075                 if (printfromdisknotice)
1076                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1077                 return shaderstring;
1078         }
1079         // fall back to builtinstring
1080         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1081 }
1082
1083 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1084 {
1085         int i;
1086         int ubibind;
1087         int sampler;
1088         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1089         char *sourcestring;
1090         char permutationname[256];
1091         int vertstrings_count = 0;
1092         int geomstrings_count = 0;
1093         int fragstrings_count = 0;
1094         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1096         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1097
1098         if (p->compiled)
1099                 return;
1100         p->compiled = true;
1101         p->program = 0;
1102
1103         permutationname[0] = 0;
1104         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1105
1106         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1107
1108         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1109         if(vid.support.glshaderversion >= 140)
1110         {
1111                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1112                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1113                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1114                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1115                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1116                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1117         }
1118         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1119         else if(vid.support.glshaderversion >= 130)
1120         {
1121                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1122                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1123                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1124                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1125                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1126                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1127         }
1128         // if we can do #version 120, we should (this adds the invariant keyword)
1129         else if(vid.support.glshaderversion >= 120)
1130         {
1131                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1132                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1133                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1134                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1135                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1136                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1137         }
1138         // GLES also adds several things from GLSL120
1139         switch(vid.renderpath)
1140         {
1141         case RENDERPATH_GLES2:
1142                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1143                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1144                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1145                 break;
1146         default:
1147                 break;
1148         }
1149
1150         // the first pretext is which type of shader to compile as
1151         // (later these will all be bound together as a program object)
1152         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1153         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1154         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1155
1156         // the second pretext is the mode (for example a light source)
1157         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1158         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1159         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1160         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1161
1162         // now add all the permutation pretexts
1163         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1164         {
1165                 if (permutation & (1ll<<i))
1166                 {
1167                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1168                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1169                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1170                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1171                 }
1172                 else
1173                 {
1174                         // keep line numbers correct
1175                         vertstrings_list[vertstrings_count++] = "\n";
1176                         geomstrings_list[geomstrings_count++] = "\n";
1177                         fragstrings_list[fragstrings_count++] = "\n";
1178                 }
1179         }
1180
1181         // add static parms
1182         R_CompileShader_AddStaticParms(mode, permutation);
1183         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1184         vertstrings_count += shaderstaticparms_count;
1185         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1186         geomstrings_count += shaderstaticparms_count;
1187         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1188         fragstrings_count += shaderstaticparms_count;
1189
1190         // now append the shader text itself
1191         vertstrings_list[vertstrings_count++] = sourcestring;
1192         geomstrings_list[geomstrings_count++] = sourcestring;
1193         fragstrings_list[fragstrings_count++] = sourcestring;
1194
1195         // compile the shader program
1196         if (vertstrings_count + geomstrings_count + fragstrings_count)
1197                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1198         if (p->program)
1199         {
1200                 CHECKGLERROR
1201                 qglUseProgram(p->program);CHECKGLERROR
1202                 // look up all the uniform variable names we care about, so we don't
1203                 // have to look them up every time we set them
1204
1205 #if 0
1206                 // debugging aid
1207                 {
1208                         GLint activeuniformindex = 0;
1209                         GLint numactiveuniforms = 0;
1210                         char uniformname[128];
1211                         GLsizei uniformnamelength = 0;
1212                         GLint uniformsize = 0;
1213                         GLenum uniformtype = 0;
1214                         memset(uniformname, 0, sizeof(uniformname));
1215                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1216                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1217                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1218                         {
1219                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1220                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1221                         }
1222                 }
1223 #endif
1224
1225                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1226                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1227                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1228                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1229                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1230                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1231                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1232                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1233                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1234                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1235                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1236                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1237                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1238                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1239                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1240                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1241                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1242                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1243                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1244                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1245                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1246                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1247                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1248                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1249                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1250                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1251                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1252                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1253                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1254                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1255                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1256                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1257                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1258                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1259                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1260                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1261                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1262                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1263                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1264                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1265                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1266                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1267                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1268                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1269                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1270                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1271                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1272                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1273                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1274                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1275                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1276                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1277                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1278                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1279                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1280                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1281                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1282                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1283                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1284                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1285                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1286                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1287                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1288                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1289                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1290                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1291                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1292                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1293                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1294                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1295                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1296                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1297                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1298                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1299                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1300                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1301                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1302                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1303                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1304                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1305                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1306                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1307                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1308                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1309                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1310                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1311                 // initialize the samplers to refer to the texture units we use
1312                 p->tex_Texture_First = -1;
1313                 p->tex_Texture_Second = -1;
1314                 p->tex_Texture_GammaRamps = -1;
1315                 p->tex_Texture_Normal = -1;
1316                 p->tex_Texture_Color = -1;
1317                 p->tex_Texture_Gloss = -1;
1318                 p->tex_Texture_Glow = -1;
1319                 p->tex_Texture_SecondaryNormal = -1;
1320                 p->tex_Texture_SecondaryColor = -1;
1321                 p->tex_Texture_SecondaryGloss = -1;
1322                 p->tex_Texture_SecondaryGlow = -1;
1323                 p->tex_Texture_Pants = -1;
1324                 p->tex_Texture_Shirt = -1;
1325                 p->tex_Texture_FogHeightTexture = -1;
1326                 p->tex_Texture_FogMask = -1;
1327                 p->tex_Texture_Lightmap = -1;
1328                 p->tex_Texture_Deluxemap = -1;
1329                 p->tex_Texture_Attenuation = -1;
1330                 p->tex_Texture_Cube = -1;
1331                 p->tex_Texture_Refraction = -1;
1332                 p->tex_Texture_Reflection = -1;
1333                 p->tex_Texture_ShadowMap2D = -1;
1334                 p->tex_Texture_CubeProjection = -1;
1335                 p->tex_Texture_ScreenNormalMap = -1;
1336                 p->tex_Texture_ScreenDiffuse = -1;
1337                 p->tex_Texture_ScreenSpecular = -1;
1338                 p->tex_Texture_ReflectMask = -1;
1339                 p->tex_Texture_ReflectCube = -1;
1340                 p->tex_Texture_BounceGrid = -1;
1341                 // bind the texture samplers in use
1342                 sampler = 0;
1343                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1344                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1345                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1346                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1347                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1348                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1349                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1350                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1351                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1352                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1353                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1354                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1355                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1356                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1357                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1358                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1359                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1360                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1361                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1362                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1363                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1364                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1365                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1366                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1367                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1368                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1369                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1370                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1371                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1372                 // get the uniform block indices so we can bind them
1373 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1374                 if (vid.support.arb_uniform_buffer_object)
1375                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1376                 else
1377 #endif
1378                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1379                 // clear the uniform block bindings
1380                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1381                 // bind the uniform blocks in use
1382                 ubibind = 0;
1383 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1384                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1385 #endif
1386                 // we're done compiling and setting up the shader, at least until it is used
1387                 CHECKGLERROR
1388                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1389         }
1390         else
1391                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1392
1393         // free the strings
1394         if (sourcestring)
1395                 Mem_Free(sourcestring);
1396 }
1397
1398 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1399 {
1400         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1401         if (r_glsl_permutation != perm)
1402         {
1403                 r_glsl_permutation = perm;
1404                 if (!r_glsl_permutation->program)
1405                 {
1406                         if (!r_glsl_permutation->compiled)
1407                         {
1408                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1409                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1410                         }
1411                         if (!r_glsl_permutation->program)
1412                         {
1413                                 // remove features until we find a valid permutation
1414                                 int i;
1415                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1416                                 {
1417                                         // reduce i more quickly whenever it would not remove any bits
1418                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1419                                         if (!(permutation & j))
1420                                                 continue;
1421                                         permutation -= j;
1422                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1423                                         if (!r_glsl_permutation->compiled)
1424                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1425                                         if (r_glsl_permutation->program)
1426                                                 break;
1427                                 }
1428                                 if (i >= SHADERPERMUTATION_COUNT)
1429                                 {
1430                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1431                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1432                                         qglUseProgram(0);CHECKGLERROR
1433                                         return; // no bit left to clear, entire mode is broken
1434                                 }
1435                         }
1436                 }
1437                 CHECKGLERROR
1438                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1439         }
1440         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1441         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1442         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1443         CHECKGLERROR
1444 }
1445
1446 #ifdef SUPPORTD3D
1447
1448 #ifdef SUPPORTD3D
1449 #include <d3d9.h>
1450 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1451 extern D3DCAPS9 vid_d3d9caps;
1452 #endif
1453
1454 struct r_hlsl_permutation_s;
1455 typedef struct r_hlsl_permutation_s
1456 {
1457         /// hash lookup data
1458         struct r_hlsl_permutation_s *hashnext;
1459         unsigned int mode;
1460         dpuint64 permutation;
1461
1462         /// indicates if we have tried compiling this permutation already
1463         qboolean compiled;
1464         /// NULL if compilation failed
1465         IDirect3DVertexShader9 *vertexshader;
1466         IDirect3DPixelShader9 *pixelshader;
1467 }
1468 r_hlsl_permutation_t;
1469
1470 typedef enum D3DVSREGISTER_e
1471 {
1472         D3DVSREGISTER_TexMatrix = 0, // float4x4
1473         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1474         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1475         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1476         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1477         D3DVSREGISTER_ModelToLight = 20, // float4x4
1478         D3DVSREGISTER_EyePosition = 24,
1479         D3DVSREGISTER_FogPlane = 25,
1480         D3DVSREGISTER_LightDir = 26,
1481         D3DVSREGISTER_LightPosition = 27,
1482 }
1483 D3DVSREGISTER_t;
1484
1485 typedef enum D3DPSREGISTER_e
1486 {
1487         D3DPSREGISTER_Alpha = 0,
1488         D3DPSREGISTER_BloomBlur_Parameters = 1,
1489         D3DPSREGISTER_ClientTime = 2,
1490         D3DPSREGISTER_Color_Ambient = 3,
1491         D3DPSREGISTER_Color_Diffuse = 4,
1492         D3DPSREGISTER_Color_Specular = 5,
1493         D3DPSREGISTER_Color_Glow = 6,
1494         D3DPSREGISTER_Color_Pants = 7,
1495         D3DPSREGISTER_Color_Shirt = 8,
1496         D3DPSREGISTER_DeferredColor_Ambient = 9,
1497         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1498         D3DPSREGISTER_DeferredColor_Specular = 11,
1499         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1500         D3DPSREGISTER_DeferredMod_Specular = 13,
1501         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1502         D3DPSREGISTER_EyePosition = 15, // unused
1503         D3DPSREGISTER_FogColor = 16,
1504         D3DPSREGISTER_FogHeightFade = 17,
1505         D3DPSREGISTER_FogPlane = 18,
1506         D3DPSREGISTER_FogPlaneViewDist = 19,
1507         D3DPSREGISTER_FogRangeRecip = 20,
1508         D3DPSREGISTER_LightColor = 21,
1509         D3DPSREGISTER_LightDir = 22, // unused
1510         D3DPSREGISTER_LightPosition = 23,
1511         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1512         D3DPSREGISTER_PixelSize = 25,
1513         D3DPSREGISTER_ReflectColor = 26,
1514         D3DPSREGISTER_ReflectFactor = 27,
1515         D3DPSREGISTER_ReflectOffset = 28,
1516         D3DPSREGISTER_RefractColor = 29,
1517         D3DPSREGISTER_Saturation = 30,
1518         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1519         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1520         D3DPSREGISTER_ScreenToDepth = 33,
1521         D3DPSREGISTER_ShadowMap_Parameters = 34,
1522         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1523         D3DPSREGISTER_SpecularPower = 36,
1524         D3DPSREGISTER_UserVec1 = 37,
1525         D3DPSREGISTER_UserVec2 = 38,
1526         D3DPSREGISTER_UserVec3 = 39,
1527         D3DPSREGISTER_UserVec4 = 40,
1528         D3DPSREGISTER_ViewTintColor = 41,
1529         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1530         D3DPSREGISTER_BloomColorSubtract = 43,
1531         D3DPSREGISTER_ViewToLight = 44, // float4x4
1532         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1533         D3DPSREGISTER_NormalmapScrollBlend = 52,
1534         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1535         D3DPSREGISTER_OffsetMapping_Bias = 54,
1536         // next at 54
1537 }
1538 D3DPSREGISTER_t;
1539
1540 /// information about each possible shader permutation
1541 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1542 /// currently selected permutation
1543 r_hlsl_permutation_t *r_hlsl_permutation;
1544 /// storage for permutations linked in the hash table
1545 memexpandablearray_t r_hlsl_permutationarray;
1546
1547 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1548 {
1549         //unsigned int hashdepth = 0;
1550         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1551         r_hlsl_permutation_t *p;
1552         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1553         {
1554                 if (p->mode == mode && p->permutation == permutation)
1555                 {
1556                         //if (hashdepth > 10)
1557                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1558                         return p;
1559                 }
1560                 //hashdepth++;
1561         }
1562         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1563         p->mode = mode;
1564         p->permutation = permutation;
1565         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1566         r_hlsl_permutationhash[mode][hashindex] = p;
1567         //if (hashdepth > 10)
1568         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1569         return p;
1570 }
1571
1572 #include <d3dx9.h>
1573 //#include <d3dx9shader.h>
1574 //#include <d3dx9mesh.h>
1575
1576 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1577 {
1578         DWORD *vsbin = NULL;
1579         DWORD *psbin = NULL;
1580         fs_offset_t vsbinsize;
1581         fs_offset_t psbinsize;
1582 //      IDirect3DVertexShader9 *vs = NULL;
1583 //      IDirect3DPixelShader9 *ps = NULL;
1584         ID3DXBuffer *vslog = NULL;
1585         ID3DXBuffer *vsbuffer = NULL;
1586         ID3DXConstantTable *vsconstanttable = NULL;
1587         ID3DXBuffer *pslog = NULL;
1588         ID3DXBuffer *psbuffer = NULL;
1589         ID3DXConstantTable *psconstanttable = NULL;
1590         int vsresult = 0;
1591         int psresult = 0;
1592         char temp[MAX_INPUTLINE];
1593         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1594         char vabuf[1024];
1595         qboolean debugshader = gl_paranoid.integer != 0;
1596         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1597         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1598         if (!debugshader)
1599         {
1600                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1601                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1602         }
1603         if ((!vsbin && vertstring) || (!psbin && fragstring))
1604         {
1605                 const char* dllnames_d3dx9 [] =
1606                 {
1607                         "d3dx9_43.dll",
1608                         "d3dx9_42.dll",
1609                         "d3dx9_41.dll",
1610                         "d3dx9_40.dll",
1611                         "d3dx9_39.dll",
1612                         "d3dx9_38.dll",
1613                         "d3dx9_37.dll",
1614                         "d3dx9_36.dll",
1615                         "d3dx9_35.dll",
1616                         "d3dx9_34.dll",
1617                         "d3dx9_33.dll",
1618                         "d3dx9_32.dll",
1619                         "d3dx9_31.dll",
1620                         "d3dx9_30.dll",
1621                         "d3dx9_29.dll",
1622                         "d3dx9_28.dll",
1623                         "d3dx9_27.dll",
1624                         "d3dx9_26.dll",
1625                         "d3dx9_25.dll",
1626                         "d3dx9_24.dll",
1627                         NULL
1628                 };
1629                 dllhandle_t d3dx9_dll = NULL;
1630                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1631                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1632                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1633                 dllfunction_t d3dx9_dllfuncs[] =
1634                 {
1635                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1636                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1637                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1638                         {NULL, NULL}
1639                 };
1640                 // 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...
1641 #ifndef ID3DXBuffer_GetBufferPointer
1642 #if !defined(__cplusplus) || defined(CINTERFACE)
1643 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1644 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1645 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1646 #else
1647 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1648 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1649 #define ID3DXBuffer_Release(p)            (p)->Release()
1650 #endif
1651 #endif
1652                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1653                 {
1654                         DWORD shaderflags = 0;
1655                         if (debugshader)
1656                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1657                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1658                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1659                         if (vertstring && vertstring[0])
1660                         {
1661                                 if (debugshader)
1662                                 {
1663                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1664                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1665                                 }
1666                                 else
1667                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1668                                 if (vsbuffer)
1669                                 {
1670                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1671                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1672                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1673                                         ID3DXBuffer_Release(vsbuffer);
1674                                 }
1675                                 if (vslog)
1676                                 {
1677                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1678                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1679                                         ID3DXBuffer_Release(vslog);
1680                                 }
1681                         }
1682                         if (fragstring && fragstring[0])
1683                         {
1684                                 if (debugshader)
1685                                 {
1686                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1687                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1688                                 }
1689                                 else
1690                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1691                                 if (psbuffer)
1692                                 {
1693                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1694                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1695                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1696                                         ID3DXBuffer_Release(psbuffer);
1697                                 }
1698                                 if (pslog)
1699                                 {
1700                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1701                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1702                                         ID3DXBuffer_Release(pslog);
1703                                 }
1704                         }
1705                         Sys_UnloadLibrary(&d3dx9_dll);
1706                 }
1707                 else
1708                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1709         }
1710         if (vsbin && psbin)
1711         {
1712                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1713                 if (FAILED(vsresult))
1714                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1715                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1716                 if (FAILED(psresult))
1717                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1718         }
1719         // free the shader data
1720         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1721         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1722 }
1723
1724 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1725 {
1726         int i;
1727         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1728         int vertstring_length = 0;
1729         int geomstring_length = 0;
1730         int fragstring_length = 0;
1731         char *t;
1732         char *sourcestring;
1733         char *vertstring, *geomstring, *fragstring;
1734         char permutationname[256];
1735         char cachename[256];
1736         int vertstrings_count = 0;
1737         int geomstrings_count = 0;
1738         int fragstrings_count = 0;
1739         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1741         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1742
1743         if (p->compiled)
1744                 return;
1745         p->compiled = true;
1746         p->vertexshader = NULL;
1747         p->pixelshader = NULL;
1748
1749         permutationname[0] = 0;
1750         cachename[0] = 0;
1751         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1752
1753         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1754         strlcat(cachename, "hlsl/", sizeof(cachename));
1755
1756         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1757         vertstrings_count = 0;
1758         geomstrings_count = 0;
1759         fragstrings_count = 0;
1760         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1761         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1762         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1763
1764         // the first pretext is which type of shader to compile as
1765         // (later these will all be bound together as a program object)
1766         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1767         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1768         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1769
1770         // the second pretext is the mode (for example a light source)
1771         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1772         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1773         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1774         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1775         strlcat(cachename, modeinfo->name, sizeof(cachename));
1776
1777         // now add all the permutation pretexts
1778         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1779         {
1780                 if (permutation & (1ll<<i))
1781                 {
1782                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1783                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1784                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1785                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1786                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1787                 }
1788                 else
1789                 {
1790                         // keep line numbers correct
1791                         vertstrings_list[vertstrings_count++] = "\n";
1792                         geomstrings_list[geomstrings_count++] = "\n";
1793                         fragstrings_list[fragstrings_count++] = "\n";
1794                 }
1795         }
1796
1797         // add static parms
1798         R_CompileShader_AddStaticParms(mode, permutation);
1799         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1800         vertstrings_count += shaderstaticparms_count;
1801         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1802         geomstrings_count += shaderstaticparms_count;
1803         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1804         fragstrings_count += shaderstaticparms_count;
1805
1806         // replace spaces in the cachename with _ characters
1807         for (i = 0;cachename[i];i++)
1808                 if (cachename[i] == ' ')
1809                         cachename[i] = '_';
1810
1811         // now append the shader text itself
1812         vertstrings_list[vertstrings_count++] = sourcestring;
1813         geomstrings_list[geomstrings_count++] = sourcestring;
1814         fragstrings_list[fragstrings_count++] = sourcestring;
1815
1816         vertstring_length = 0;
1817         for (i = 0;i < vertstrings_count;i++)
1818                 vertstring_length += (int)strlen(vertstrings_list[i]);
1819         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1820         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1821                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1822
1823         geomstring_length = 0;
1824         for (i = 0;i < geomstrings_count;i++)
1825                 geomstring_length += (int)strlen(geomstrings_list[i]);
1826         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1827         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1828                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1829
1830         fragstring_length = 0;
1831         for (i = 0;i < fragstrings_count;i++)
1832                 fragstring_length += (int)strlen(fragstrings_list[i]);
1833         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1834         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1835                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1836
1837         // try to load the cached shader, or generate one
1838         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1839
1840         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1841                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1842         else
1843                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1844
1845         // free the strings
1846         if (vertstring)
1847                 Mem_Free(vertstring);
1848         if (geomstring)
1849                 Mem_Free(geomstring);
1850         if (fragstring)
1851                 Mem_Free(fragstring);
1852         if (sourcestring)
1853                 Mem_Free(sourcestring);
1854 }
1855
1856 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1857 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1858 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);}
1859 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);}
1860 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);}
1861 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);}
1862
1863 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1864 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1865 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);}
1866 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);}
1867 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);}
1868 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);}
1869
1870 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1871 {
1872         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1873         if (r_hlsl_permutation != perm)
1874         {
1875                 r_hlsl_permutation = perm;
1876                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1877                 {
1878                         if (!r_hlsl_permutation->compiled)
1879                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1880                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1881                         {
1882                                 // remove features until we find a valid permutation
1883                                 int i;
1884                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1885                                 {
1886                                         // reduce i more quickly whenever it would not remove any bits
1887                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1888                                         if (!(permutation & j))
1889                                                 continue;
1890                                         permutation -= j;
1891                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1892                                         if (!r_hlsl_permutation->compiled)
1893                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1894                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1895                                                 break;
1896                                 }
1897                                 if (i >= SHADERPERMUTATION_COUNT)
1898                                 {
1899                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1900                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1901                                         return; // no bit left to clear, entire mode is broken
1902                                 }
1903                         }
1904                 }
1905                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1906                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1907         }
1908         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1909         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1910         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1911 }
1912 #endif
1913
1914 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1915 {
1916         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1917         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1918         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1919         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1920 }
1921
1922 void R_GLSL_Restart_f(void)
1923 {
1924         unsigned int i, limit;
1925         switch(vid.renderpath)
1926         {
1927         case RENDERPATH_D3D9:
1928 #ifdef SUPPORTD3D
1929                 {
1930                         r_hlsl_permutation_t *p;
1931                         r_hlsl_permutation = NULL;
1932                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1933                         for (i = 0;i < limit;i++)
1934                         {
1935                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1936                                 {
1937                                         if (p->vertexshader)
1938                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1939                                         if (p->pixelshader)
1940                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1941                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1942                                 }
1943                         }
1944                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1945                 }
1946 #endif
1947                 break;
1948         case RENDERPATH_D3D10:
1949                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1950                 break;
1951         case RENDERPATH_D3D11:
1952                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1953                 break;
1954         case RENDERPATH_GL20:
1955         case RENDERPATH_GLES2:
1956                 {
1957                         r_glsl_permutation_t *p;
1958                         r_glsl_permutation = NULL;
1959                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1960                         for (i = 0;i < limit;i++)
1961                         {
1962                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1963                                 {
1964                                         GL_Backend_FreeProgram(p->program);
1965                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1966                                 }
1967                         }
1968                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1969                 }
1970                 break;
1971         case RENDERPATH_GL11:
1972         case RENDERPATH_GL13:
1973         case RENDERPATH_GLES1:
1974                 break;
1975         case RENDERPATH_SOFT:
1976                 break;
1977         }
1978 }
1979
1980 static void R_GLSL_DumpShader_f(void)
1981 {
1982         int i, language, mode, dupe;
1983         char *text;
1984         shadermodeinfo_t *modeinfo;
1985         qfile_t *file;
1986
1987         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1988         {
1989                 modeinfo = shadermodeinfo[language];
1990                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1991                 {
1992                         // don't dump the same file multiple times (most or all shaders come from the same file)
1993                         for (dupe = mode - 1;dupe >= 0;dupe--)
1994                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1995                                         break;
1996                         if (dupe >= 0)
1997                                 continue;
1998                         text = modeinfo[mode].builtinstring;
1999                         if (!text)
2000                                 continue;
2001                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
2002                         if (file)
2003                         {
2004                                 FS_Print(file, "/* The engine may define the following macros:\n");
2005                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2006                                 for (i = 0;i < SHADERMODE_COUNT;i++)
2007                                         FS_Print(file, modeinfo[i].pretext);
2008                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2009                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2010                                 FS_Print(file, "*/\n");
2011                                 FS_Print(file, text);
2012                                 FS_Close(file);
2013                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2014                         }
2015                         else
2016                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2017                 }
2018         }
2019 }
2020
2021 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2022 {
2023         dpuint64 permutation = 0;
2024         if (r_trippy.integer && !notrippy)
2025                 permutation |= SHADERPERMUTATION_TRIPPY;
2026         permutation |= SHADERPERMUTATION_VIEWTINT;
2027         if (first)
2028                 permutation |= SHADERPERMUTATION_DIFFUSE;
2029         if (second)
2030                 permutation |= SHADERPERMUTATION_SPECULAR;
2031         if (texturemode == GL_MODULATE)
2032                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2033         else if (texturemode == GL_ADD)
2034                 permutation |= SHADERPERMUTATION_GLOW;
2035         else if (texturemode == GL_DECAL)
2036                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2037         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2038                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2039         if (suppresstexalpha)
2040                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2041         if (!second)
2042                 texturemode = GL_MODULATE;
2043         if (vid.allowalphatocoverage)
2044                 GL_AlphaToCoverage(false);
2045         switch (vid.renderpath)
2046         {
2047         case RENDERPATH_D3D9:
2048 #ifdef SUPPORTD3D
2049                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2050                 R_Mesh_TexBind(GL20TU_FIRST , first );
2051                 R_Mesh_TexBind(GL20TU_SECOND, second);
2052                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2053                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2054 #endif
2055                 break;
2056         case RENDERPATH_D3D10:
2057                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2058                 break;
2059         case RENDERPATH_D3D11:
2060                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2061                 break;
2062         case RENDERPATH_GL20:
2063         case RENDERPATH_GLES2:
2064                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2065                 if (r_glsl_permutation->tex_Texture_First >= 0)
2066                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2067                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2068                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2069                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2070                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2071                 break;
2072         case RENDERPATH_GL13:
2073         case RENDERPATH_GLES1:
2074                 R_Mesh_TexBind(0, first );
2075                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2076                 R_Mesh_TexMatrix(0, NULL);
2077                 R_Mesh_TexBind(1, second);
2078                 if (second)
2079                 {
2080                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2081                         R_Mesh_TexMatrix(1, NULL);
2082                 }
2083                 break;
2084         case RENDERPATH_GL11:
2085                 R_Mesh_TexBind(0, first );
2086                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2087                 R_Mesh_TexMatrix(0, NULL);
2088                 break;
2089         case RENDERPATH_SOFT:
2090                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2091                 R_Mesh_TexBind(GL20TU_FIRST , first );
2092                 R_Mesh_TexBind(GL20TU_SECOND, second);
2093                 break;
2094         }
2095 }
2096
2097 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2098 {
2099         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2100 }
2101
2102 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2103 {
2104         dpuint64 permutation = 0;
2105         if (r_trippy.integer && !notrippy)
2106                 permutation |= SHADERPERMUTATION_TRIPPY;
2107         if (depthrgb)
2108                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2109         if (skeletal)
2110                 permutation |= SHADERPERMUTATION_SKELETAL;
2111
2112         if (vid.allowalphatocoverage)
2113                 GL_AlphaToCoverage(false);
2114         switch (vid.renderpath)
2115         {
2116         case RENDERPATH_D3D9:
2117 #ifdef SUPPORTD3D
2118                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2119 #endif
2120                 break;
2121         case RENDERPATH_D3D10:
2122                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2123                 break;
2124         case RENDERPATH_D3D11:
2125                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2126                 break;
2127         case RENDERPATH_GL20:
2128         case RENDERPATH_GLES2:
2129                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2130 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2131                 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);
2132 #endif
2133                 break;
2134         case RENDERPATH_GL13:
2135         case RENDERPATH_GLES1:
2136                 R_Mesh_TexBind(0, 0);
2137                 R_Mesh_TexBind(1, 0);
2138                 break;
2139         case RENDERPATH_GL11:
2140                 R_Mesh_TexBind(0, 0);
2141                 break;
2142         case RENDERPATH_SOFT:
2143                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2144                 break;
2145         }
2146 }
2147
2148 extern qboolean r_shadow_usingdeferredprepass;
2149 extern rtexture_t *r_shadow_attenuationgradienttexture;
2150 extern rtexture_t *r_shadow_attenuation2dtexture;
2151 extern rtexture_t *r_shadow_attenuation3dtexture;
2152 extern qboolean r_shadow_usingshadowmap2d;
2153 extern qboolean r_shadow_usingshadowmaportho;
2154 extern float r_shadow_modelshadowmap_texturescale[4];
2155 extern float r_shadow_modelshadowmap_parameters[4];
2156 extern float r_shadow_lightshadowmap_texturescale[4];
2157 extern float r_shadow_lightshadowmap_parameters[4];
2158 extern qboolean r_shadow_shadowmapvsdct;
2159 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2160 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2161 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2162 extern matrix4x4_t r_shadow_shadowmapmatrix;
2163 extern int r_shadow_prepass_width;
2164 extern int r_shadow_prepass_height;
2165 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2166 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2167 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2168 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2169
2170 #define BLENDFUNC_ALLOWS_COLORMOD      1
2171 #define BLENDFUNC_ALLOWS_FOG           2
2172 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2173 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2174 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2175 static int R_BlendFuncFlags(int src, int dst)
2176 {
2177         int r = 0;
2178
2179         // a blendfunc allows colormod if:
2180         // a) it can never keep the destination pixel invariant, or
2181         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2182         // this is to prevent unintended side effects from colormod
2183
2184         // a blendfunc allows fog if:
2185         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2186         // this is to prevent unintended side effects from fog
2187
2188         // these checks are the output of fogeval.pl
2189
2190         r |= BLENDFUNC_ALLOWS_COLORMOD;
2191         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2192         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2193         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2194         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2195         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2197         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2198         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2199         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2200         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2201         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2202         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2203         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2204         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2205         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2206         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2207         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2208         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2209         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2210         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2211         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2212
2213         return r;
2214 }
2215
2216 void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2217 {
2218         // select a permutation of the lighting shader appropriate to this
2219         // combination of texture, entity, light source, and fogging, only use the
2220         // minimum features necessary to avoid wasting rendering time in the
2221         // fragment shader on features that are not being used
2222         dpuint64 permutation = 0;
2223         unsigned int mode = 0;
2224         int blendfuncflags;
2225         texture_t *t = rsurface.texture;
2226         float m16f[16];
2227         matrix4x4_t tempmatrix;
2228         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2229         if (r_trippy.integer && !notrippy)
2230                 permutation |= SHADERPERMUTATION_TRIPPY;
2231         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2232                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2233         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2234                 permutation |= SHADERPERMUTATION_OCCLUDE;
2235         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2236                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2237         if (rsurfacepass == RSURFPASS_BACKGROUND)
2238         {
2239                 // distorted background
2240                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2241                 {
2242                         mode = SHADERMODE_WATER;
2243                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2244                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2245                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2246                         {
2247                                 // this is the right thing to do for wateralpha
2248                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2249                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2250                         }
2251                         else
2252                         {
2253                                 // this is the right thing to do for entity alpha
2254                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2255                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2256                         }
2257                 }
2258                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2259                 {
2260                         mode = SHADERMODE_REFRACTION;
2261                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2262                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2263                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2264                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2265                 }
2266                 else
2267                 {
2268                         mode = SHADERMODE_GENERIC;
2269                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2270                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2271                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2272                 }
2273                 if (vid.allowalphatocoverage)
2274                         GL_AlphaToCoverage(false);
2275         }
2276         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2277         {
2278                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2279                 {
2280                         switch(t->offsetmapping)
2281                         {
2282                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2283                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2284                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285                         case OFFSETMAPPING_OFF: break;
2286                         }
2287                 }
2288                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2289                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2290                 // normalmap (deferred prepass), may use alpha test on diffuse
2291                 mode = SHADERMODE_DEFERREDGEOMETRY;
2292                 GL_BlendFunc(GL_ONE, GL_ZERO);
2293                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2294                 if (vid.allowalphatocoverage)
2295                         GL_AlphaToCoverage(false);
2296         }
2297         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2298         {
2299                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2300                 {
2301                         switch(t->offsetmapping)
2302                         {
2303                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2304                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2305                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2306                         case OFFSETMAPPING_OFF: break;
2307                         }
2308                 }
2309                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2310                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2311                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2312                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2313                 // light source
2314                 mode = SHADERMODE_LIGHTSOURCE;
2315                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2316                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2317                 if (VectorLength2(rtlightdiffuse) > 0)
2318                         permutation |= SHADERPERMUTATION_DIFFUSE;
2319                 if (VectorLength2(rtlightspecular) > 0)
2320                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2321                 if (r_refdef.fogenabled)
2322                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2323                 if (t->colormapping)
2324                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2325                 if (r_shadow_usingshadowmap2d)
2326                 {
2327                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2328                         if(r_shadow_shadowmapvsdct)
2329                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2330
2331                         if (r_shadow_shadowmap2ddepthbuffer)
2332                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2333                 }
2334                 if (t->reflectmasktexture)
2335                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2336                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2337                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2338                 if (vid.allowalphatocoverage)
2339                         GL_AlphaToCoverage(false);
2340         }
2341         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2342         {
2343                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2344                 {
2345                         switch(t->offsetmapping)
2346                         {
2347                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2348                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350                         case OFFSETMAPPING_OFF: break;
2351                         }
2352                 }
2353                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2354                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2355                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2356                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2357                 // directional model lighting
2358                 mode = SHADERMODE_LIGHTDIRECTION;
2359                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2360                         permutation |= SHADERPERMUTATION_GLOW;
2361                 if (VectorLength2(t->render_modellight_diffuse))
2362                         permutation |= SHADERPERMUTATION_DIFFUSE;
2363                 if (VectorLength2(t->render_modellight_specular) > 0)
2364                         permutation |= SHADERPERMUTATION_SPECULAR;
2365                 if (r_refdef.fogenabled)
2366                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2367                 if (t->colormapping)
2368                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2369                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2370                 {
2371                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2372                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2373
2374                         if (r_shadow_shadowmap2ddepthbuffer)
2375                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2376                 }
2377                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2378                         permutation |= SHADERPERMUTATION_REFLECTION;
2379                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2380                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2381                 if (t->reflectmasktexture)
2382                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2383                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2384                 {
2385                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2386                         if (r_shadow_bouncegrid_state.directional)
2387                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2388                 }
2389                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2390                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2391                 // when using alphatocoverage, we don't need alphakill
2392                 if (vid.allowalphatocoverage)
2393                 {
2394                         if (r_transparent_alphatocoverage.integer)
2395                         {
2396                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2397                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2398                         }
2399                         else
2400                                 GL_AlphaToCoverage(false);
2401                 }
2402         }
2403         else
2404         {
2405                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2406                 {
2407                         switch(t->offsetmapping)
2408                         {
2409                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2410                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2411                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2412                         case OFFSETMAPPING_OFF: break;
2413                         }
2414                 }
2415                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2416                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2417                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2418                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2419                 // lightmapped wall
2420                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2421                         permutation |= SHADERPERMUTATION_GLOW;
2422                 if (r_refdef.fogenabled)
2423                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2424                 if (t->colormapping)
2425                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2426                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2427                 {
2428                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2429                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2430
2431                         if (r_shadow_shadowmap2ddepthbuffer)
2432                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2433                 }
2434                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2435                         permutation |= SHADERPERMUTATION_REFLECTION;
2436                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2437                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2438                 if (t->reflectmasktexture)
2439                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2440                 if (FAKELIGHT_ENABLED)
2441                 {
2442                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2443                         mode = SHADERMODE_FAKELIGHT;
2444                         permutation |= SHADERPERMUTATION_DIFFUSE;
2445                         if (VectorLength2(t->render_lightmap_specular) > 0)
2446                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2447                 }
2448                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2449                 {
2450                         // deluxemapping (light direction texture)
2451                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2452                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2453                         else
2454                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2455                         permutation |= SHADERPERMUTATION_DIFFUSE;
2456                         if (VectorLength2(t->render_lightmap_specular) > 0)
2457                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2458                 }
2459                 else if (r_glsl_deluxemapping.integer >= 2)
2460                 {
2461                         // fake deluxemapping (uniform light direction in tangentspace)
2462                         if (rsurface.uselightmaptexture)
2463                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2464                         else
2465                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2466                         permutation |= SHADERPERMUTATION_DIFFUSE;
2467                         if (VectorLength2(t->render_lightmap_specular) > 0)
2468                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2469                 }
2470                 else if (rsurface.uselightmaptexture)
2471                 {
2472                         // ordinary lightmapping (q1bsp, q3bsp)
2473                         mode = SHADERMODE_LIGHTMAP;
2474                 }
2475                 else
2476                 {
2477                         // ordinary vertex coloring (q3bsp)
2478                         mode = SHADERMODE_VERTEXCOLOR;
2479                 }
2480                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2481                 {
2482                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2483                         if (r_shadow_bouncegrid_state.directional)
2484                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2485                 }
2486                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2487                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2488                 // when using alphatocoverage, we don't need alphakill
2489                 if (vid.allowalphatocoverage)
2490                 {
2491                         if (r_transparent_alphatocoverage.integer)
2492                         {
2493                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2494                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2495                         }
2496                         else
2497                                 GL_AlphaToCoverage(false);
2498                 }
2499         }
2500         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2501                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2502         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2503                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2504         switch(vid.renderpath)
2505         {
2506         case RENDERPATH_D3D9:
2507 #ifdef SUPPORTD3D
2508                 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);
2509                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2510                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2511                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2512                 if (mode == SHADERMODE_LIGHTSOURCE)
2513                 {
2514                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2515                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2516                 }
2517                 else
2518                 {
2519                         if (mode == SHADERMODE_LIGHTDIRECTION)
2520                         {
2521                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2522                         }
2523                 }
2524                 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2525                 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2526                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2527                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2528                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2529
2530                 if (mode == SHADERMODE_LIGHTSOURCE)
2531                 {
2532                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2533                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2537
2538                         // additive passes are only darkened by fog, not tinted
2539                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2540                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2541                 }
2542                 else
2543                 {
2544                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2545                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2546                         if (mode == SHADERMODE_FLATCOLOR)
2547                         {
2548                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2549                         }
2550                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2551                         {
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2557                         }
2558                         else
2559                         {
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2563                         }
2564                         // additive passes are only darkened by fog, not tinted
2565                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2567                         else
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2569                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2570                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2571                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2572                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2574                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2575                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2576                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2577                         if (mode == SHADERMODE_WATER)
2578                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2579                 }
2580                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2581                 {
2582                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2583                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2584                 }
2585                 else
2586                 {
2587                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2588                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2589                 }
2590                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2591                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2592                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2593                 if (t->pantstexture)
2594                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2595                 else
2596                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2597                 if (t->shirttexture)
2598                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2599                 else
2600                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2601                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2602                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2603                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2604                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2605                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2606                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2607                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2608                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2609                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2610                         );
2611                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2612                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2613                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2614                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2615
2616                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2617                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2618                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2619                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2620                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2621                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2622                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2623                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2624                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2625                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2626                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2627                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2628                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2629                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2630                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2631                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2632                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2633                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2634                 {
2635                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2636                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2637                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2638                 }
2639                 else
2640                 {
2641                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2642                 }
2643 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2644                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2645                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2646                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2647                 {
2648                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2649                         if (rsurface.rtlight)
2650                         {
2651                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2652                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2653                         }
2654                 }
2655 #endif
2656                 break;
2657         case RENDERPATH_D3D10:
2658                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2659                 break;
2660         case RENDERPATH_D3D11:
2661                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2662                 break;
2663         case RENDERPATH_GL20:
2664         case RENDERPATH_GLES2:
2665                 if (!vid.useinterleavedarrays)
2666                 {
2667                         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);
2668                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2669                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2670                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2671                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2672                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2673                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2674                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2675                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2676                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2677                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2678                 }
2679                 else
2680                 {
2681                         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);
2682                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2683                 }
2684                 // this has to be after RSurf_PrepareVerticesForBatch
2685                 if (rsurface.batchskeletaltransform3x4buffer)
2686                         permutation |= SHADERPERMUTATION_SKELETAL;
2687                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2688 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2689                 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);
2690 #endif
2691                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2692                 if (mode == SHADERMODE_LIGHTSOURCE)
2693                 {
2694                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2695                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2696                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2697                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2698                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2699                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2700         
2701                         // additive passes are only darkened by fog, not tinted
2702                         if (r_glsl_permutation->loc_FogColor >= 0)
2703                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2704                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2705                 }
2706                 else
2707                 {
2708                         if (mode == SHADERMODE_FLATCOLOR)
2709                         {
2710                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2711                         }
2712                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2713                         {
2714                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2715                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2716                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2717                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2718                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2719                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2720                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2721                         }
2722                         else
2723                         {
2724                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2725                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2726                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2727                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2728                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2729                         }
2730                         // additive passes are only darkened by fog, not tinted
2731                         if (r_glsl_permutation->loc_FogColor >= 0)
2732                         {
2733                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2734                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2735                                 else
2736                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2737                         }
2738                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2739                         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]);
2740                         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]);
2741                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2742                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2743                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2744                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2745                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2746                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2747                 }
2748                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2749                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2750                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2751                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2752                 {
2753                         if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2754                         if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2755                 }
2756                 else
2757                 {
2758                         if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2759                         if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2760                 }
2761
2762                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2763                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2764                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2765                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2766                 {
2767                         if (t->pantstexture)
2768                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2769                         else
2770                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2771                 }
2772                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2773                 {
2774                         if (t->shirttexture)
2775                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2776                         else
2777                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2778                 }
2779                 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]);
2780                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2781                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2782                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2783                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2784                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2785                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2786                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2787                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2788                         );
2789                 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);
2790                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2791                 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]);
2792                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2793                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2794                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2795
2796                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2797                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2798                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2799                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
2800                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
2801                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
2802                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
2803                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
2804                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
2805                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
2806                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
2807                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2808                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2809                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2810                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2811                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2812                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2813                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2814                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2815                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2816                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2817                 {
2818                         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);
2819                         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);
2820                         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);
2821                 }
2822                 else
2823                 {
2824                         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);
2825                 }
2826                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2827                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2828                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2829                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2830                 {
2831                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2832                         if (rsurface.rtlight)
2833                         {
2834                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2835                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2836                         }
2837                 }
2838                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2839                 CHECKGLERROR
2840                 break;
2841         case RENDERPATH_GL11:
2842         case RENDERPATH_GL13:
2843         case RENDERPATH_GLES1:
2844                 break;
2845         case RENDERPATH_SOFT:
2846                 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);
2847                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2848                 R_SetupShader_SetPermutationSoft(mode, permutation);
2849                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2850                 if (mode == SHADERMODE_LIGHTSOURCE)
2851                 {
2852                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2853                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2854                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2855                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2858         
2859                         // additive passes are only darkened by fog, not tinted
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2861                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2862                 }
2863                 else
2864                 {
2865                         if (mode == SHADERMODE_FLATCOLOR)
2866                         {
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2868                         }
2869                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2870                         {
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2876                         }
2877                         else
2878                         {
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2882                         }
2883                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2884                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2885                         // additive passes are only darkened by fog, not tinted
2886                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2888                         else
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2890                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2891                         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]);
2892                         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]);
2893                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2894                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2895                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2896                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2897                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2898                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2899                 }
2900                 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2901                 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2902                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2903                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2904                 {
2905                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2906                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2907                 }
2908                 else
2909                 {
2910                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2911                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2912                 }
2913
2914                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2915                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2916                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2917                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2918                 {
2919                         if (t->pantstexture)
2920                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2921                         else
2922                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2923                 }
2924                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2925                 {
2926                         if (t->shirttexture)
2927                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2928                         else
2929                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2930                 }
2931                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2933                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2934                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2935                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2936                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2937                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2938                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2939                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2940                         );
2941                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2942                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2943                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2944                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2945
2946                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2947                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2948                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2949                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2951                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2952                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2953                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2954                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2955                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2956                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2957                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2958                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2959                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2960                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2961                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2962                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2963                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2964                 {
2965                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2966                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2967                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2968                 }
2969                 else
2970                 {
2971                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2972                 }
2973 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2974                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2975                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2976                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2977                 {
2978                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2979                         if (rsurface.rtlight)
2980                         {
2981                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2982                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2983                         }
2984                 }
2985                 break;
2986         }
2987 }
2988
2989 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2990 {
2991         // select a permutation of the lighting shader appropriate to this
2992         // combination of texture, entity, light source, and fogging, only use the
2993         // minimum features necessary to avoid wasting rendering time in the
2994         // fragment shader on features that are not being used
2995         dpuint64 permutation = 0;
2996         unsigned int mode = 0;
2997         const float *lightcolorbase = rtlight->currentcolor;
2998         float ambientscale = rtlight->ambientscale;
2999         float diffusescale = rtlight->diffusescale;
3000         float specularscale = rtlight->specularscale;
3001         // this is the location of the light in view space
3002         vec3_t viewlightorigin;
3003         // this transforms from view space (camera) to light space (cubemap)
3004         matrix4x4_t viewtolight;
3005         matrix4x4_t lighttoview;
3006         float viewtolight16f[16];
3007         // light source
3008         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3009         if (rtlight->currentcubemap != r_texture_whitecube)
3010                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3011         if (diffusescale > 0)
3012                 permutation |= SHADERPERMUTATION_DIFFUSE;
3013         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3014                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3015         if (r_shadow_usingshadowmap2d)
3016         {
3017                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3018                 if (r_shadow_shadowmapvsdct)
3019                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3020
3021                 if (r_shadow_shadowmap2ddepthbuffer)
3022                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3023         }
3024         if (vid.allowalphatocoverage)
3025                 GL_AlphaToCoverage(false);
3026         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3027         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3028         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3029         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3030         switch(vid.renderpath)
3031         {
3032         case RENDERPATH_D3D9:
3033 #ifdef SUPPORTD3D
3034                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3035                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3036                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3037                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3038                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3039                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3040                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3041                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3042                 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);
3043                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3044                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3045
3046                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3047                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3048                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3049                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3050                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3051 #endif
3052                 break;
3053         case RENDERPATH_D3D10:
3054                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3055                 break;
3056         case RENDERPATH_D3D11:
3057                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3058                 break;
3059         case RENDERPATH_GL20:
3060         case RENDERPATH_GLES2:
3061                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3062                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3063                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3064                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3065                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3066                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3067                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3068                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3069                 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);
3070                 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]);
3071                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3072
3073                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3074                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3075                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3076                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3077                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3078                 break;
3079         case RENDERPATH_GL11:
3080         case RENDERPATH_GL13:
3081         case RENDERPATH_GLES1:
3082                 break;
3083         case RENDERPATH_SOFT:
3084                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3086                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3087                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3088                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3089                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3090                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3091                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3092                 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);
3093                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3094                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3095
3096                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3097                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3098                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3099                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3100                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3101                 break;
3102         }
3103 }
3104
3105 #define SKINFRAME_HASH 1024
3106
3107 typedef struct
3108 {
3109         unsigned int loadsequence; // incremented each level change
3110         memexpandablearray_t array;
3111         skinframe_t *hash[SKINFRAME_HASH];
3112 }
3113 r_skinframe_t;
3114 r_skinframe_t r_skinframe;
3115
3116 void R_SkinFrame_PrepareForPurge(void)
3117 {
3118         r_skinframe.loadsequence++;
3119         // wrap it without hitting zero
3120         if (r_skinframe.loadsequence >= 200)
3121                 r_skinframe.loadsequence = 1;
3122 }
3123
3124 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3125 {
3126         if (!skinframe)
3127                 return;
3128         // mark the skinframe as used for the purging code
3129         skinframe->loadsequence = r_skinframe.loadsequence;
3130 }
3131
3132 void R_SkinFrame_Purge(void)
3133 {
3134         int i;
3135         skinframe_t *s;
3136         for (i = 0;i < SKINFRAME_HASH;i++)
3137         {
3138                 for (s = r_skinframe.hash[i];s;s = s->next)
3139                 {
3140                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3141                         {
3142                                 if (s->merged == s->base)
3143                                         s->merged = NULL;
3144                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3145                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3146                                 R_PurgeTexture(s->merged);s->merged = NULL;
3147                                 R_PurgeTexture(s->base  );s->base   = NULL;
3148                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3149                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3150                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3151                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3152                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3153                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3154                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3155                                 s->loadsequence = 0;
3156                         }
3157                 }
3158         }
3159 }
3160
3161 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3162         skinframe_t *item;
3163         char basename[MAX_QPATH];
3164
3165         Image_StripImageExtension(name, basename, sizeof(basename));
3166
3167         if( last == NULL ) {
3168                 int hashindex;
3169                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3170                 item = r_skinframe.hash[hashindex];
3171         } else {
3172                 item = last->next;
3173         }
3174
3175         // linearly search through the hash bucket
3176         for( ; item ; item = item->next ) {
3177                 if( !strcmp( item->basename, basename ) ) {
3178                         return item;
3179                 }
3180         }
3181         return NULL;
3182 }
3183
3184 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3185 {
3186         skinframe_t *item;
3187         int hashindex;
3188         char basename[MAX_QPATH];
3189
3190         Image_StripImageExtension(name, basename, sizeof(basename));
3191
3192         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3193         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3194                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3195                         break;
3196
3197         if (!item) {
3198                 rtexture_t *dyntexture;
3199                 // check whether its a dynamic texture
3200                 dyntexture = CL_GetDynTexture( basename );
3201                 if (!add && !dyntexture)
3202                         return NULL;
3203                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3204                 memset(item, 0, sizeof(*item));
3205                 strlcpy(item->basename, basename, sizeof(item->basename));
3206                 item->base = dyntexture; // either NULL or dyntexture handle
3207                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3208                 item->comparewidth = comparewidth;
3209                 item->compareheight = compareheight;
3210                 item->comparecrc = comparecrc;
3211                 item->next = r_skinframe.hash[hashindex];
3212                 r_skinframe.hash[hashindex] = item;
3213         }
3214         else if (textureflags & TEXF_FORCE_RELOAD)
3215         {
3216                 rtexture_t *dyntexture;
3217                 // check whether its a dynamic texture
3218                 dyntexture = CL_GetDynTexture( basename );
3219                 if (!add && !dyntexture)
3220                         return NULL;
3221                 if (item->merged == item->base)
3222                         item->merged = NULL;
3223                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3224                 R_PurgeTexture(item->stain );item->stain  = NULL;
3225                 R_PurgeTexture(item->merged);item->merged = NULL;
3226                 R_PurgeTexture(item->base  );item->base   = NULL;
3227                 R_PurgeTexture(item->pants );item->pants  = NULL;
3228                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3229                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3230                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3231                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3232                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3233         R_PurgeTexture(item->reflect);item->reflect = NULL;
3234                 item->loadsequence = 0;
3235         }
3236         else if( item->base == NULL )
3237         {
3238                 rtexture_t *dyntexture;
3239                 // check whether its a dynamic texture
3240                 // 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]
3241                 dyntexture = CL_GetDynTexture( basename );
3242                 item->base = dyntexture; // either NULL or dyntexture handle
3243         }
3244
3245         R_SkinFrame_MarkUsed(item);
3246         return item;
3247 }
3248
3249 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3250         { \
3251                 unsigned long long avgcolor[5], wsum; \
3252                 int pix, comp, w; \
3253                 avgcolor[0] = 0; \
3254                 avgcolor[1] = 0; \
3255                 avgcolor[2] = 0; \
3256                 avgcolor[3] = 0; \
3257                 avgcolor[4] = 0; \
3258                 wsum = 0; \
3259                 for(pix = 0; pix < cnt; ++pix) \
3260                 { \
3261                         w = 0; \
3262                         for(comp = 0; comp < 3; ++comp) \
3263                                 w += getpixel; \
3264                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3265                         { \
3266                                 ++wsum; \
3267                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3268                                 w = getpixel; \
3269                                 for(comp = 0; comp < 3; ++comp) \
3270                                         avgcolor[comp] += getpixel * w; \
3271                                 avgcolor[3] += w; \
3272                         } \
3273                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3274                         avgcolor[4] += getpixel; \
3275                 } \
3276                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3277                         avgcolor[3] = 1; \
3278                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3279                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3280                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3281                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3282         }
3283
3284 extern cvar_t gl_picmip;
3285 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3286 {
3287         int j;
3288         unsigned char *pixels;
3289         unsigned char *bumppixels;
3290         unsigned char *basepixels = NULL;
3291         int basepixels_width = 0;
3292         int basepixels_height = 0;
3293         skinframe_t *skinframe;
3294         rtexture_t *ddsbase = NULL;
3295         qboolean ddshasalpha = false;
3296         float ddsavgcolor[4];
3297         char basename[MAX_QPATH];
3298         int miplevel = R_PicmipForFlags(textureflags);
3299         int savemiplevel = miplevel;
3300         int mymiplevel;
3301         char vabuf[1024];
3302
3303         if (cls.state == ca_dedicated)
3304                 return NULL;
3305
3306         // return an existing skinframe if already loaded
3307         // if loading of the first image fails, don't make a new skinframe as it
3308         // would cause all future lookups of this to be missing
3309         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3310         if (skinframe && skinframe->base)
3311                 return skinframe;
3312
3313         Image_StripImageExtension(name, basename, sizeof(basename));
3314
3315         // check for DDS texture file first
3316         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3317         {
3318                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3319                 if (basepixels == NULL)
3320                         return NULL;
3321         }
3322
3323         // FIXME handle miplevel
3324
3325         if (developer_loading.integer)
3326                 Con_Printf("loading skin \"%s\"\n", name);
3327
3328         // we've got some pixels to store, so really allocate this new texture now
3329         if (!skinframe)
3330                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3331         textureflags &= ~TEXF_FORCE_RELOAD;
3332         skinframe->stain = NULL;
3333         skinframe->merged = NULL;
3334         skinframe->base = NULL;
3335         skinframe->pants = NULL;
3336         skinframe->shirt = NULL;
3337         skinframe->nmap = NULL;
3338         skinframe->gloss = NULL;
3339         skinframe->glow = NULL;
3340         skinframe->fog = NULL;
3341         skinframe->reflect = NULL;
3342         skinframe->hasalpha = false;
3343         // we could store the q2animname here too
3344
3345         if (ddsbase)
3346         {
3347                 skinframe->base = ddsbase;
3348                 skinframe->hasalpha = ddshasalpha;
3349                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3350                 if (r_loadfog && skinframe->hasalpha)
3351                         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);
3352                 //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]);
3353         }
3354         else
3355         {
3356                 basepixels_width = image_width;
3357                 basepixels_height = image_height;
3358                 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);
3359                 if (textureflags & TEXF_ALPHA)
3360                 {
3361                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3362                         {
3363                                 if (basepixels[j] < 255)
3364                                 {
3365                                         skinframe->hasalpha = true;
3366                                         break;
3367                                 }
3368                         }
3369                         if (r_loadfog && skinframe->hasalpha)
3370                         {
3371                                 // has transparent pixels
3372                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3373                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3374                                 {
3375                                         pixels[j+0] = 255;
3376                                         pixels[j+1] = 255;
3377                                         pixels[j+2] = 255;
3378                                         pixels[j+3] = basepixels[j+3];
3379                                 }
3380                                 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);
3381                                 Mem_Free(pixels);
3382                         }
3383                 }
3384                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3385 #ifndef USE_GLES2
3386                 //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]);
3387                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3388                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3389                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3390                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3391 #endif
3392         }
3393
3394         if (r_loaddds)
3395         {
3396                 mymiplevel = savemiplevel;
3397                 if (r_loadnormalmap)
3398                         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);
3399                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3400                 if (r_loadgloss)
3401                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3402                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3403                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3404                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3405         }
3406
3407         // _norm is the name used by tenebrae and has been adopted as standard
3408         if (r_loadnormalmap && skinframe->nmap == NULL)
3409         {
3410                 mymiplevel = savemiplevel;
3411                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3412                 {
3413                         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);
3414                         Mem_Free(pixels);
3415                         pixels = NULL;
3416                 }
3417                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3418                 {
3419                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3420                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3421                         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);
3422                         Mem_Free(pixels);
3423                         Mem_Free(bumppixels);
3424                 }
3425                 else if (r_shadow_bumpscale_basetexture.value > 0)
3426                 {
3427                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3428                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3429                         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);
3430                         Mem_Free(pixels);
3431                 }
3432 #ifndef USE_GLES2
3433                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3434                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3435 #endif
3436         }
3437
3438         // _luma is supported only for tenebrae compatibility
3439         // _glow is the preferred name
3440         mymiplevel = savemiplevel;
3441         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))))
3442         {
3443                 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);
3444 #ifndef USE_GLES2
3445                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3446                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3447 #endif
3448                 Mem_Free(pixels);pixels = NULL;
3449         }
3450
3451         mymiplevel = savemiplevel;
3452         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3453         {
3454                 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);
3455 #ifndef USE_GLES2
3456                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3457                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3458 #endif
3459                 Mem_Free(pixels);
3460                 pixels = NULL;
3461         }
3462
3463         mymiplevel = savemiplevel;
3464         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3465         {
3466                 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);
3467 #ifndef USE_GLES2
3468                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3469                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3470 #endif
3471                 Mem_Free(pixels);
3472                 pixels = NULL;
3473         }
3474
3475         mymiplevel = savemiplevel;
3476         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3477         {
3478                 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);
3479 #ifndef USE_GLES2
3480                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3481                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3482 #endif
3483                 Mem_Free(pixels);
3484                 pixels = NULL;
3485         }
3486
3487         mymiplevel = savemiplevel;
3488         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3489         {
3490                 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);
3491 #ifndef USE_GLES2
3492                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3493                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3494 #endif
3495                 Mem_Free(pixels);
3496                 pixels = NULL;
3497         }
3498
3499         if (basepixels)
3500                 Mem_Free(basepixels);
3501
3502         return skinframe;
3503 }
3504
3505 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3506 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3507 {
3508         int i;
3509         skinframe_t *skinframe;
3510         char vabuf[1024];
3511
3512         if (cls.state == ca_dedicated)
3513                 return NULL;
3514
3515         // if already loaded just return it, otherwise make a new skinframe
3516         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3517         if (skinframe->base)
3518                 return skinframe;
3519         textureflags &= ~TEXF_FORCE_RELOAD;
3520
3521         skinframe->stain = NULL;
3522         skinframe->merged = NULL;
3523         skinframe->base = NULL;
3524         skinframe->pants = NULL;
3525         skinframe->shirt = NULL;
3526         skinframe->nmap = NULL;
3527         skinframe->gloss = NULL;
3528         skinframe->glow = NULL;
3529         skinframe->fog = NULL;
3530         skinframe->reflect = NULL;
3531         skinframe->hasalpha = false;
3532
3533         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3534         if (!skindata)
3535                 return NULL;
3536
3537         if (developer_loading.integer)
3538                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3539
3540         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3541         {
3542                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3543                 unsigned char *b = a + width * height * 4;
3544                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3545                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3546                 Mem_Free(a);
3547         }
3548         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3549         if (textureflags & TEXF_ALPHA)
3550         {
3551                 for (i = 3;i < width * height * 4;i += 4)
3552                 {
3553                         if (skindata[i] < 255)
3554                         {
3555                                 skinframe->hasalpha = true;
3556                                 break;
3557                         }
3558                 }
3559                 if (r_loadfog && skinframe->hasalpha)
3560                 {
3561                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3562                         memcpy(fogpixels, skindata, width * height * 4);
3563                         for (i = 0;i < width * height * 4;i += 4)
3564                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3565                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3566                         Mem_Free(fogpixels);
3567                 }
3568         }
3569
3570         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3571         //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]);
3572
3573         return skinframe;
3574 }
3575
3576 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3577 {
3578         int i;
3579         int featuresmask;
3580         skinframe_t *skinframe;
3581
3582         if (cls.state == ca_dedicated)
3583                 return NULL;
3584
3585         // if already loaded just return it, otherwise make a new skinframe
3586         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3587         if (skinframe->base)
3588                 return skinframe;
3589         //textureflags &= ~TEXF_FORCE_RELOAD;
3590
3591         skinframe->stain = NULL;
3592         skinframe->merged = NULL;
3593         skinframe->base = NULL;
3594         skinframe->pants = NULL;
3595         skinframe->shirt = NULL;
3596         skinframe->nmap = NULL;
3597         skinframe->gloss = NULL;
3598         skinframe->glow = NULL;
3599         skinframe->fog = NULL;
3600         skinframe->reflect = NULL;
3601         skinframe->hasalpha = false;
3602
3603         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3604         if (!skindata)
3605                 return NULL;
3606
3607         if (developer_loading.integer)
3608                 Con_Printf("loading quake skin \"%s\"\n", name);
3609
3610         // 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)
3611         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3612         memcpy(skinframe->qpixels, skindata, width*height);
3613         skinframe->qwidth = width;
3614         skinframe->qheight = height;
3615
3616         featuresmask = 0;
3617         for (i = 0;i < width * height;i++)
3618                 featuresmask |= palette_featureflags[skindata[i]];
3619
3620         skinframe->hasalpha = false;
3621         // fence textures
3622         if (name[0] == '{')
3623                 skinframe->hasalpha = true;
3624         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3625         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3626         skinframe->qgeneratemerged = true;
3627         skinframe->qgeneratebase = skinframe->qhascolormapping;
3628         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3629
3630         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3631         //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]);
3632
3633         return skinframe;
3634 }
3635
3636 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3637 {
3638         int width;
3639         int height;
3640         unsigned char *skindata;
3641         char vabuf[1024];
3642
3643         if (!skinframe->qpixels)
3644                 return;
3645
3646         if (!skinframe->qhascolormapping)
3647                 colormapped = false;
3648
3649         if (colormapped)
3650         {
3651                 if (!skinframe->qgeneratebase)
3652                         return;
3653         }
3654         else
3655         {
3656                 if (!skinframe->qgeneratemerged)
3657                         return;
3658         }
3659
3660         width = skinframe->qwidth;
3661         height = skinframe->qheight;
3662         skindata = skinframe->qpixels;
3663
3664         if (skinframe->qgeneratenmap)
3665         {
3666                 unsigned char *a, *b;
3667                 skinframe->qgeneratenmap = false;
3668                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3669                 b = a + width * height * 4;
3670                 // use either a custom palette or the quake palette
3671                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3672                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3673                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3674                 Mem_Free(a);
3675         }
3676
3677         if (skinframe->qgenerateglow)
3678         {
3679                 skinframe->qgenerateglow = false;
3680                 if (skinframe->hasalpha) // fence textures
3681                         skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, palette_bgra_onlyfullbrights_transparent); // glow
3682                 else
3683                         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
3684         }
3685
3686         if (colormapped)
3687         {
3688                 skinframe->qgeneratebase = false;
3689                 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);
3690                 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);
3691                 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);
3692         }
3693         else
3694         {
3695                 skinframe->qgeneratemerged = false;
3696                 if (skinframe->hasalpha) // fence textures
3697                         skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, skinframe->glow ? palette_bgra_nofullbrights_transparent : palette_bgra_transparent);
3698                 else
3699                         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);
3700         }
3701
3702         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3703         {
3704                 Mem_Free(skinframe->qpixels);
3705                 skinframe->qpixels = NULL;
3706         }
3707 }
3708
3709 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)
3710 {
3711         int i;
3712         skinframe_t *skinframe;
3713         char vabuf[1024];
3714
3715         if (cls.state == ca_dedicated)
3716                 return NULL;
3717
3718         // if already loaded just return it, otherwise make a new skinframe
3719         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3720         if (skinframe->base)
3721                 return skinframe;
3722         textureflags &= ~TEXF_FORCE_RELOAD;
3723
3724         skinframe->stain = NULL;
3725         skinframe->merged = NULL;
3726         skinframe->base = NULL;
3727         skinframe->pants = NULL;
3728         skinframe->shirt = NULL;
3729         skinframe->nmap = NULL;
3730         skinframe->gloss = NULL;
3731         skinframe->glow = NULL;
3732         skinframe->fog = NULL;
3733         skinframe->reflect = NULL;
3734         skinframe->hasalpha = false;
3735
3736         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3737         if (!skindata)
3738                 return NULL;
3739
3740         if (developer_loading.integer)
3741                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3742
3743         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3744         if (textureflags & TEXF_ALPHA)
3745         {
3746                 for (i = 0;i < width * height;i++)
3747                 {
3748                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3749                         {
3750                                 skinframe->hasalpha = true;
3751                                 break;
3752                         }
3753                 }
3754                 if (r_loadfog && skinframe->hasalpha)
3755                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3756         }
3757
3758         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3759         //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]);
3760
3761         return skinframe;
3762 }
3763
3764 skinframe_t *R_SkinFrame_LoadMissing(void)
3765 {
3766         skinframe_t *skinframe;
3767
3768         if (cls.state == ca_dedicated)
3769                 return NULL;
3770
3771         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3772         skinframe->stain = NULL;
3773         skinframe->merged = NULL;
3774         skinframe->base = NULL;
3775         skinframe->pants = NULL;
3776         skinframe->shirt = NULL;
3777         skinframe->nmap = NULL;
3778         skinframe->gloss = NULL;
3779         skinframe->glow = NULL;
3780         skinframe->fog = NULL;
3781         skinframe->reflect = NULL;
3782         skinframe->hasalpha = false;
3783
3784         skinframe->avgcolor[0] = rand() / RAND_MAX;
3785         skinframe->avgcolor[1] = rand() / RAND_MAX;
3786         skinframe->avgcolor[2] = rand() / RAND_MAX;
3787         skinframe->avgcolor[3] = 1;
3788
3789         return skinframe;
3790 }
3791
3792 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3793 typedef struct suffixinfo_s
3794 {
3795         const char *suffix;
3796         qboolean flipx, flipy, flipdiagonal;
3797 }
3798 suffixinfo_t;
3799 static suffixinfo_t suffix[3][6] =
3800 {
3801         {
3802                 {"px",   false, false, false},
3803                 {"nx",   false, false, false},
3804                 {"py",   false, false, false},
3805                 {"ny",   false, false, false},
3806                 {"pz",   false, false, false},
3807                 {"nz",   false, false, false}
3808         },
3809         {
3810                 {"posx", false, false, false},
3811                 {"negx", false, false, false},
3812                 {"posy", false, false, false},
3813                 {"negy", false, false, false},
3814                 {"posz", false, false, false},
3815                 {"negz", false, false, false}
3816         },
3817         {
3818                 {"rt",    true, false,  true},
3819                 {"lf",   false,  true,  true},
3820                 {"ft",    true,  true, false},
3821                 {"bk",   false, false, false},
3822                 {"up",    true, false,  true},
3823                 {"dn",    true, false,  true}
3824         }
3825 };
3826
3827 static int componentorder[4] = {0, 1, 2, 3};
3828
3829 static rtexture_t *R_LoadCubemap(const char *basename)
3830 {
3831         int i, j, cubemapsize;
3832         unsigned char *cubemappixels, *image_buffer;
3833         rtexture_t *cubemaptexture;
3834         char name[256];
3835         // must start 0 so the first loadimagepixels has no requested width/height
3836         cubemapsize = 0;
3837         cubemappixels = NULL;
3838         cubemaptexture = NULL;
3839         // keep trying different suffix groups (posx, px, rt) until one loads
3840         for (j = 0;j < 3 && !cubemappixels;j++)
3841         {
3842                 // load the 6 images in the suffix group
3843                 for (i = 0;i < 6;i++)
3844                 {
3845                         // generate an image name based on the base and and suffix
3846                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3847                         // load it
3848                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3849                         {
3850                                 // an image loaded, make sure width and height are equal
3851                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3852                                 {
3853                                         // if this is the first image to load successfully, allocate the cubemap memory
3854                                         if (!cubemappixels && image_width >= 1)
3855                                         {
3856                                                 cubemapsize = image_width;
3857                                                 // note this clears to black, so unavailable sides are black
3858                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3859                                         }
3860                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3861                                         if (cubemappixels)
3862                                                 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);
3863                                 }
3864                                 else
3865                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3866                                 // free the image
3867                                 Mem_Free(image_buffer);
3868                         }
3869                 }
3870         }
3871         // if a cubemap loaded, upload it
3872         if (cubemappixels)
3873         {
3874                 if (developer_loading.integer)
3875                         Con_Printf("loading cubemap \"%s\"\n", basename);
3876
3877                 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);
3878                 Mem_Free(cubemappixels);
3879         }
3880         else
3881         {
3882                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3883                 if (developer_loading.integer)
3884                 {
3885                         Con_Printf("(tried tried images ");
3886                         for (j = 0;j < 3;j++)
3887                                 for (i = 0;i < 6;i++)
3888                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3889                         Con_Print(" and was unable to find any of them).\n");
3890                 }
3891         }
3892         return cubemaptexture;
3893 }
3894
3895 rtexture_t *R_GetCubemap(const char *basename)
3896 {
3897         int i;
3898         for (i = 0;i < r_texture_numcubemaps;i++)
3899                 if (r_texture_cubemaps[i] != NULL)
3900                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3901                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3902         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3903                 return r_texture_whitecube;
3904         r_texture_numcubemaps++;
3905         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3906         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3907         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3908         return r_texture_cubemaps[i]->texture;
3909 }
3910
3911 static void R_Main_FreeViewCache(void)
3912 {
3913         if (r_refdef.viewcache.entityvisible)
3914                 Mem_Free(r_refdef.viewcache.entityvisible);
3915         if (r_refdef.viewcache.world_pvsbits)
3916                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3917         if (r_refdef.viewcache.world_leafvisible)
3918                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3919         if (r_refdef.viewcache.world_surfacevisible)
3920                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3921         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3922 }
3923
3924 static void R_Main_ResizeViewCache(void)
3925 {
3926         int numentities = r_refdef.scene.numentities;
3927         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3928         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3929         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3930         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3931         if (r_refdef.viewcache.maxentities < numentities)
3932         {
3933                 r_refdef.viewcache.maxentities = numentities;
3934                 if (r_refdef.viewcache.entityvisible)
3935                         Mem_Free(r_refdef.viewcache.entityvisible);
3936                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3937         }
3938         if (r_refdef.viewcache.world_numclusters != numclusters)
3939         {
3940                 r_refdef.viewcache.world_numclusters = numclusters;
3941                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3942                 if (r_refdef.viewcache.world_pvsbits)
3943                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3944                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3945         }
3946         if (r_refdef.viewcache.world_numleafs != numleafs)
3947         {
3948                 r_refdef.viewcache.world_numleafs = numleafs;
3949                 if (r_refdef.viewcache.world_leafvisible)
3950                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3951                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3952         }
3953         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3954         {
3955                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3956                 if (r_refdef.viewcache.world_surfacevisible)
3957                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3958                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3959         }
3960 }
3961
3962 extern rtexture_t *loadingscreentexture;
3963 static void gl_main_start(void)
3964 {
3965         loadingscreentexture = NULL;
3966         r_texture_blanknormalmap = NULL;
3967         r_texture_white = NULL;
3968         r_texture_grey128 = NULL;
3969         r_texture_black = NULL;
3970         r_texture_whitecube = NULL;
3971         r_texture_normalizationcube = NULL;
3972         r_texture_fogattenuation = NULL;
3973         r_texture_fogheighttexture = NULL;
3974         r_texture_gammaramps = NULL;
3975         r_texture_numcubemaps = 0;
3976         r_uniformbufferalignment = 32;
3977
3978         r_loaddds = r_texture_dds_load.integer != 0;
3979         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3980
3981         switch(vid.renderpath)
3982         {
3983         case RENDERPATH_GL20:
3984         case RENDERPATH_D3D9:
3985         case RENDERPATH_D3D10:
3986         case RENDERPATH_D3D11:
3987         case RENDERPATH_SOFT:
3988         case RENDERPATH_GLES2:
3989                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3990                 Cvar_SetValueQuick(&gl_combine, 1);
3991                 Cvar_SetValueQuick(&r_glsl, 1);
3992                 r_loadnormalmap = true;
3993                 r_loadgloss = true;
3994                 r_loadfog = false;
3995 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
3996                 if (vid.support.arb_uniform_buffer_object)
3997                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
3998 #endif
3999                         break;
4000         case RENDERPATH_GL13:
4001         case RENDERPATH_GLES1:
4002                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4003                 Cvar_SetValueQuick(&gl_combine, 1);
4004                 Cvar_SetValueQuick(&r_glsl, 0);
4005                 r_loadnormalmap = false;
4006                 r_loadgloss = false;
4007                 r_loadfog = true;
4008                 break;
4009         case RENDERPATH_GL11:
4010                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4011                 Cvar_SetValueQuick(&gl_combine, 0);
4012                 Cvar_SetValueQuick(&r_glsl, 0);
4013                 r_loadnormalmap = false;
4014                 r_loadgloss = false;
4015                 r_loadfog = true;
4016                 break;
4017         }
4018
4019         R_AnimCache_Free();
4020         R_FrameData_Reset();
4021         R_BufferData_Reset();
4022
4023         r_numqueries = 0;
4024         r_maxqueries = 0;
4025         memset(r_queries, 0, sizeof(r_queries));
4026
4027         r_qwskincache = NULL;
4028         r_qwskincache_size = 0;
4029
4030         // due to caching of texture_t references, the collision cache must be reset
4031         Collision_Cache_Reset(true);
4032
4033         // set up r_skinframe loading system for textures
4034         memset(&r_skinframe, 0, sizeof(r_skinframe));
4035         r_skinframe.loadsequence = 1;
4036         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4037
4038         r_main_texturepool = R_AllocTexturePool();
4039         R_BuildBlankTextures();
4040         R_BuildNoTexture();
4041         if (vid.support.arb_texture_cube_map)
4042         {
4043                 R_BuildWhiteCube();
4044                 R_BuildNormalizationCube();
4045         }
4046         r_texture_fogattenuation = NULL;
4047         r_texture_fogheighttexture = NULL;
4048         r_texture_gammaramps = NULL;
4049         //r_texture_fogintensity = NULL;
4050         memset(&r_fb, 0, sizeof(r_fb));
4051         r_glsl_permutation = NULL;
4052         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4053         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4054 #ifdef SUPPORTD3D
4055         r_hlsl_permutation = NULL;
4056         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4057         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4058 #endif
4059         memset(&r_svbsp, 0, sizeof (r_svbsp));
4060
4061         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4062         r_texture_numcubemaps = 0;
4063
4064         r_refdef.fogmasktable_density = 0;
4065
4066 #ifdef __ANDROID__
4067         // For Steelstorm Android
4068         // FIXME CACHE the program and reload
4069         // FIXME see possible combinations for SS:BR android
4070         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4071         R_SetupShader_SetPermutationGLSL(0, 12);
4072         R_SetupShader_SetPermutationGLSL(0, 13);
4073         R_SetupShader_SetPermutationGLSL(0, 8388621);
4074         R_SetupShader_SetPermutationGLSL(3, 0);
4075         R_SetupShader_SetPermutationGLSL(3, 2048);
4076         R_SetupShader_SetPermutationGLSL(5, 0);
4077         R_SetupShader_SetPermutationGLSL(5, 2);
4078         R_SetupShader_SetPermutationGLSL(5, 2048);
4079         R_SetupShader_SetPermutationGLSL(5, 8388608);
4080         R_SetupShader_SetPermutationGLSL(11, 1);
4081         R_SetupShader_SetPermutationGLSL(11, 2049);
4082         R_SetupShader_SetPermutationGLSL(11, 8193);
4083         R_SetupShader_SetPermutationGLSL(11, 10241);
4084         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4085 #endif
4086 }
4087
4088 static void gl_main_shutdown(void)
4089 {
4090         R_AnimCache_Free();
4091         R_FrameData_Reset();
4092         R_BufferData_Reset();
4093
4094         R_Main_FreeViewCache();
4095
4096         switch(vid.renderpath)
4097         {
4098         case RENDERPATH_GL11:
4099         case RENDERPATH_GL13:
4100         case RENDERPATH_GL20:
4101         case RENDERPATH_GLES1:
4102         case RENDERPATH_GLES2:
4103 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4104                 if (r_maxqueries)
4105                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4106 #endif
4107                 break;
4108         case RENDERPATH_D3D9:
4109                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4110                 break;
4111         case RENDERPATH_D3D10:
4112                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4113                 break;
4114         case RENDERPATH_D3D11:
4115                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4116                 break;
4117         case RENDERPATH_SOFT:
4118                 break;
4119         }
4120
4121         r_numqueries = 0;
4122         r_maxqueries = 0;
4123         memset(r_queries, 0, sizeof(r_queries));
4124
4125         r_qwskincache = NULL;
4126         r_qwskincache_size = 0;
4127
4128         // clear out the r_skinframe state
4129         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4130         memset(&r_skinframe, 0, sizeof(r_skinframe));
4131
4132         if (r_svbsp.nodes)
4133                 Mem_Free(r_svbsp.nodes);
4134         memset(&r_svbsp, 0, sizeof (r_svbsp));
4135         R_FreeTexturePool(&r_main_texturepool);
4136         loadingscreentexture = NULL;
4137         r_texture_blanknormalmap = NULL;
4138         r_texture_white = NULL;
4139         r_texture_grey128 = NULL;
4140         r_texture_black = NULL;
4141         r_texture_whitecube = NULL;
4142         r_texture_normalizationcube = NULL;
4143         r_texture_fogattenuation = NULL;
4144         r_texture_fogheighttexture = NULL;
4145         r_texture_gammaramps = NULL;
4146         r_texture_numcubemaps = 0;
4147         //r_texture_fogintensity = NULL;
4148         memset(&r_fb, 0, sizeof(r_fb));
4149         R_GLSL_Restart_f();
4150
4151         r_glsl_permutation = NULL;
4152         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4153         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4154 #ifdef SUPPORTD3D
4155         r_hlsl_permutation = NULL;
4156         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4157         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4158 #endif
4159 }
4160
4161 static void gl_main_newmap(void)
4162 {
4163         // FIXME: move this code to client
4164         char *entities, entname[MAX_QPATH];
4165         if (r_qwskincache)
4166                 Mem_Free(r_qwskincache);
4167         r_qwskincache = NULL;
4168         r_qwskincache_size = 0;
4169         if (cl.worldmodel)
4170         {
4171                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4172                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4173                 {
4174                         CL_ParseEntityLump(entities);
4175                         Mem_Free(entities);
4176                         return;
4177                 }
4178                 if (cl.worldmodel->brush.entities)
4179                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4180         }
4181         R_Main_FreeViewCache();
4182
4183         R_FrameData_Reset();
4184         R_BufferData_Reset();
4185 }
4186
4187 void GL_Main_Init(void)
4188 {
4189         int i;
4190         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4191         R_InitShaderModeInfo();
4192
4193         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4194         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4195         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4196         if (gamemode == GAME_NEHAHRA)
4197         {
4198                 Cvar_RegisterVariable (&gl_fogenable);
4199                 Cvar_RegisterVariable (&gl_fogdensity);
4200                 Cvar_RegisterVariable (&gl_fogred);
4201                 Cvar_RegisterVariable (&gl_foggreen);
4202                 Cvar_RegisterVariable (&gl_fogblue);
4203                 Cvar_RegisterVariable (&gl_fogstart);
4204                 Cvar_RegisterVariable (&gl_fogend);
4205                 Cvar_RegisterVariable (&gl_skyclip);
4206         }
4207         Cvar_RegisterVariable(&r_motionblur);
4208         Cvar_RegisterVariable(&r_damageblur);
4209         Cvar_RegisterVariable(&r_motionblur_averaging);
4210         Cvar_RegisterVariable(&r_motionblur_randomize);
4211         Cvar_RegisterVariable(&r_motionblur_minblur);
4212         Cvar_RegisterVariable(&r_motionblur_maxblur);
4213         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4214         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4215         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4216         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4217         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4218         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4219         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4220         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4221         Cvar_RegisterVariable(&r_equalize_entities_by);
4222         Cvar_RegisterVariable(&r_equalize_entities_to);
4223         Cvar_RegisterVariable(&r_depthfirst);
4224         Cvar_RegisterVariable(&r_useinfinitefarclip);
4225         Cvar_RegisterVariable(&r_farclip_base);
4226         Cvar_RegisterVariable(&r_farclip_world);
4227         Cvar_RegisterVariable(&r_nearclip);
4228         Cvar_RegisterVariable(&r_deformvertexes);
4229         Cvar_RegisterVariable(&r_transparent);
4230         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4231         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4232         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4233         Cvar_RegisterVariable(&r_showoverdraw);
4234         Cvar_RegisterVariable(&r_showbboxes);
4235         Cvar_RegisterVariable(&r_showbboxes_client);
4236         Cvar_RegisterVariable(&r_showsurfaces);
4237         Cvar_RegisterVariable(&r_showtris);
4238         Cvar_RegisterVariable(&r_shownormals);
4239         Cvar_RegisterVariable(&r_showlighting);
4240         Cvar_RegisterVariable(&r_showshadowvolumes);
4241         Cvar_RegisterVariable(&r_showcollisionbrushes);
4242         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4243         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4244         Cvar_RegisterVariable(&r_showdisabledepthtest);
4245         Cvar_RegisterVariable(&r_drawportals);
4246         Cvar_RegisterVariable(&r_drawentities);
4247         Cvar_RegisterVariable(&r_draw2d);
4248         Cvar_RegisterVariable(&r_drawworld);
4249         Cvar_RegisterVariable(&r_cullentities_trace);
4250         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4251         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4252         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4253         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4254         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4255         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4256         Cvar_RegisterVariable(&r_sortentities);
4257         Cvar_RegisterVariable(&r_drawviewmodel);
4258         Cvar_RegisterVariable(&r_drawexteriormodel);
4259         Cvar_RegisterVariable(&r_speeds);
4260         Cvar_RegisterVariable(&r_fullbrights);
4261         Cvar_RegisterVariable(&r_wateralpha);
4262         Cvar_RegisterVariable(&r_dynamic);
4263         Cvar_RegisterVariable(&r_fakelight);
4264         Cvar_RegisterVariable(&r_fakelight_intensity);
4265         Cvar_RegisterVariable(&r_fullbright_directed);
4266         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4267         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4268         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4269         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4270         Cvar_RegisterVariable(&r_fullbright);
4271         Cvar_RegisterVariable(&r_shadows);
4272         Cvar_RegisterVariable(&r_shadows_darken);
4273         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4274         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4275         Cvar_RegisterVariable(&r_shadows_throwdistance);
4276         Cvar_RegisterVariable(&r_shadows_throwdirection);
4277         Cvar_RegisterVariable(&r_shadows_focus);
4278         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4279         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4280         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4281         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4282         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4283         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4284         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4285         Cvar_RegisterVariable(&r_fog_exp2);
4286         Cvar_RegisterVariable(&r_fog_clear);
4287         Cvar_RegisterVariable(&r_drawfog);
4288         Cvar_RegisterVariable(&r_transparentdepthmasking);
4289         Cvar_RegisterVariable(&r_transparent_sortmindist);
4290         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4291         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4292         Cvar_RegisterVariable(&r_texture_dds_load);
4293         Cvar_RegisterVariable(&r_texture_dds_save);
4294         Cvar_RegisterVariable(&r_textureunits);
4295         Cvar_RegisterVariable(&gl_combine);
4296         Cvar_RegisterVariable(&r_usedepthtextures);
4297         Cvar_RegisterVariable(&r_viewfbo);
4298         Cvar_RegisterVariable(&r_viewscale);
4299         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4300         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4301         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4302         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4303         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4304         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4305         Cvar_RegisterVariable(&r_glsl);
4306         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4307         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4308         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4309         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4310         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4311         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4312         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4313         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4314         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4315         Cvar_RegisterVariable(&r_glsl_postprocess);
4316         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4317         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4318         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4319         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4320         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4321         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4322         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4323         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4324         Cvar_RegisterVariable(&r_celshading);
4325         Cvar_RegisterVariable(&r_celoutlines);
4326
4327         Cvar_RegisterVariable(&r_water);
4328         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4329         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4330         Cvar_RegisterVariable(&r_water_clippingplanebias);
4331         Cvar_RegisterVariable(&r_water_refractdistort);
4332         Cvar_RegisterVariable(&r_water_reflectdistort);
4333         Cvar_RegisterVariable(&r_water_scissormode);
4334         Cvar_RegisterVariable(&r_water_lowquality);
4335         Cvar_RegisterVariable(&r_water_hideplayer);
4336         Cvar_RegisterVariable(&r_water_fbo);
4337
4338         Cvar_RegisterVariable(&r_lerpsprites);
4339         Cvar_RegisterVariable(&r_lerpmodels);
4340         Cvar_RegisterVariable(&r_lerplightstyles);
4341         Cvar_RegisterVariable(&r_waterscroll);
4342         Cvar_RegisterVariable(&r_bloom);
4343         Cvar_RegisterVariable(&r_bloom_colorscale);
4344         Cvar_RegisterVariable(&r_bloom_brighten);
4345         Cvar_RegisterVariable(&r_bloom_blur);
4346         Cvar_RegisterVariable(&r_bloom_resolution);
4347         Cvar_RegisterVariable(&r_bloom_colorexponent);
4348         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4349         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4350         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4351         Cvar_RegisterVariable(&r_hdr_glowintensity);
4352         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4353         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4354         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4355         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4356         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4357         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4358         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4359         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4360         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4361         Cvar_RegisterVariable(&developer_texturelogging);
4362         Cvar_RegisterVariable(&gl_lightmaps);
4363         Cvar_RegisterVariable(&r_test);
4364         Cvar_RegisterVariable(&r_batch_multidraw);
4365         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4366         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4367         Cvar_RegisterVariable(&r_glsl_skeletal);
4368         Cvar_RegisterVariable(&r_glsl_saturation);
4369         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4370         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4371         Cvar_RegisterVariable(&r_framedatasize);
4372         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4373                 Cvar_RegisterVariable(&r_buffermegs[i]);
4374         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4375         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4376                 Cvar_SetValue("r_fullbrights", 0);
4377 #ifdef DP_MOBILETOUCH
4378         // GLES devices have terrible depth precision in general, so...
4379         Cvar_SetValueQuick(&r_nearclip, 4);
4380         Cvar_SetValueQuick(&r_farclip_base, 4096);
4381         Cvar_SetValueQuick(&r_farclip_world, 0);
4382         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4383 #endif
4384         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4385 }
4386
4387 void Render_Init(void)
4388 {
4389         gl_backend_init();
4390         R_Textures_Init();
4391         GL_Main_Init();
4392         Font_Init();
4393         GL_Draw_Init();
4394         R_Shadow_Init();
4395         R_Sky_Init();
4396         GL_Surf_Init();
4397         Sbar_Init();
4398         R_Particles_Init();
4399         R_Explosion_Init();
4400         R_LightningBeams_Init();
4401         Mod_RenderInit();
4402 }
4403
4404 /*
4405 ===============
4406 GL_Init
4407 ===============
4408 */
4409 #ifndef USE_GLES2
4410 extern char *ENGINE_EXTENSIONS;
4411 void GL_Init (void)
4412 {
4413         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4414         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4415         gl_version = (const char *)qglGetString(GL_VERSION);
4416         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4417
4418         if (!gl_extensions)
4419                 gl_extensions = "";
4420         if (!gl_platformextensions)
4421                 gl_platformextensions = "";
4422
4423         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4424         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4425         Con_Printf("GL_VERSION: %s\n", gl_version);
4426         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4427         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4428
4429         VID_CheckExtensions();
4430
4431         // LordHavoc: report supported extensions
4432 #ifdef CONFIG_MENU
4433         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4434 #else
4435         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4436 #endif
4437
4438         // clear to black (loading plaque will be seen over this)
4439         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4440 }
4441 #endif
4442
4443 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4444 {
4445         int i;
4446         mplane_t *p;
4447         if (r_trippy.integer)
4448                 return false;
4449         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4450         {
4451                 p = r_refdef.view.frustum + i;
4452                 switch(p->signbits)
4453                 {
4454                 default:
4455                 case 0:
4456                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 case 1:
4460                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4461                                 return true;
4462                         break;
4463                 case 2:
4464                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4465                                 return true;
4466                         break;
4467                 case 3:
4468                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4469                                 return true;
4470                         break;
4471                 case 4:
4472                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4473                                 return true;
4474                         break;
4475                 case 5:
4476                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4477                                 return true;
4478                         break;
4479                 case 6:
4480                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4481                                 return true;
4482                         break;
4483                 case 7:
4484                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4485                                 return true;
4486                         break;
4487                 }
4488         }
4489         return false;
4490 }
4491
4492 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4493 {
4494         int i;
4495         const mplane_t *p;
4496         if (r_trippy.integer)
4497                 return false;
4498         for (i = 0;i < numplanes;i++)
4499         {
4500                 p = planes + i;
4501                 switch(p->signbits)
4502                 {
4503                 default:
4504                 case 0:
4505                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4506                                 return true;
4507                         break;
4508                 case 1:
4509                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4510                                 return true;
4511                         break;
4512                 case 2:
4513                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4514                                 return true;
4515                         break;
4516                 case 3:
4517                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4518                                 return true;
4519                         break;
4520                 case 4:
4521                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4522                                 return true;
4523                         break;
4524                 case 5:
4525                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4526                                 return true;
4527                         break;
4528                 case 6:
4529                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4530                                 return true;
4531                         break;
4532                 case 7:
4533                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4534                                 return true;
4535                         break;
4536                 }
4537         }
4538         return false;
4539 }
4540
4541 //==================================================================================
4542
4543 // LordHavoc: this stores temporary data used within the same frame
4544
4545 typedef struct r_framedata_mem_s
4546 {
4547         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4548         size_t size; // how much usable space
4549         size_t current; // how much space in use
4550         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4551         size_t wantedsize; // how much space was allocated
4552         unsigned char *data; // start of real data (16byte aligned)
4553 }
4554 r_framedata_mem_t;
4555
4556 static r_framedata_mem_t *r_framedata_mem;
4557
4558 void R_FrameData_Reset(void)
4559 {
4560         while (r_framedata_mem)
4561         {
4562                 r_framedata_mem_t *next = r_framedata_mem->purge;
4563                 Mem_Free(r_framedata_mem);
4564                 r_framedata_mem = next;
4565         }
4566 }
4567
4568 static void R_FrameData_Resize(qboolean mustgrow)
4569 {
4570         size_t wantedsize;
4571         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4572         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4573         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4574         {
4575                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4576                 newmem->wantedsize = wantedsize;
4577                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4578                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4579                 newmem->current = 0;
4580                 newmem->mark = 0;
4581                 newmem->purge = r_framedata_mem;
4582                 r_framedata_mem = newmem;
4583         }
4584 }
4585
4586 void R_FrameData_NewFrame(void)
4587 {
4588         R_FrameData_Resize(false);
4589         if (!r_framedata_mem)
4590                 return;
4591         // if we ran out of space on the last frame, free the old memory now
4592         while (r_framedata_mem->purge)
4593         {
4594                 // repeatedly remove the second item in the list, leaving only head
4595                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4596                 Mem_Free(r_framedata_mem->purge);
4597                 r_framedata_mem->purge = next;
4598         }
4599         // reset the current mem pointer
4600         r_framedata_mem->current = 0;
4601         r_framedata_mem->mark = 0;
4602 }
4603
4604 void *R_FrameData_Alloc(size_t size)
4605 {
4606         void *data;
4607         float newvalue;
4608
4609         // align to 16 byte boundary - the data pointer is already aligned, so we
4610         // only need to ensure the size of every allocation is also aligned
4611         size = (size + 15) & ~15;
4612
4613         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4614         {
4615                 // emergency - we ran out of space, allocate more memory
4616                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4617                 newvalue = r_framedatasize.value * 2.0f;
4618                 // upper bound based on architecture - if we try to allocate more than this we could overflow, better to loop until we error out on allocation failure
4619                 if (sizeof(size_t) >= 8)
4620                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4621                 else
4622                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4623                 // this might not be a growing it, but we'll allocate another buffer every time
4624                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4625                 R_FrameData_Resize(true);
4626         }
4627
4628         data = r_framedata_mem->data + r_framedata_mem->current;
4629         r_framedata_mem->current += size;
4630
4631         // count the usage for stats
4632         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4633         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4634
4635         return (void *)data;
4636 }
4637
4638 void *R_FrameData_Store(size_t size, void *data)
4639 {
4640         void *d = R_FrameData_Alloc(size);
4641         if (d && data)
4642                 memcpy(d, data, size);
4643         return d;
4644 }
4645
4646 void R_FrameData_SetMark(void)
4647 {
4648         if (!r_framedata_mem)
4649                 return;
4650         r_framedata_mem->mark = r_framedata_mem->current;
4651 }
4652
4653 void R_FrameData_ReturnToMark(void)
4654 {
4655         if (!r_framedata_mem)
4656                 return;
4657         r_framedata_mem->current = r_framedata_mem->mark;
4658 }
4659
4660 //==================================================================================
4661
4662 // avoid reusing the same buffer objects on consecutive frames
4663 #define R_BUFFERDATA_CYCLE 3
4664
4665 typedef struct r_bufferdata_buffer_s
4666 {
4667         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4668         size_t size; // how much usable space
4669         size_t current; // how much space in use
4670         r_meshbuffer_t *buffer; // the buffer itself
4671 }
4672 r_bufferdata_buffer_t;
4673
4674 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4675 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4676
4677 /// frees all dynamic buffers
4678 void R_BufferData_Reset(void)
4679 {
4680         int cycle, type;
4681         r_bufferdata_buffer_t **p, *mem;
4682         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4683         {
4684                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4685                 {
4686                         // free all buffers
4687                         p = &r_bufferdata_buffer[cycle][type];
4688                         while (*p)
4689                         {
4690                                 mem = *p;
4691                                 *p = (*p)->purge;
4692                                 if (mem->buffer)
4693                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4694                                 Mem_Free(mem);
4695                         }
4696                 }
4697         }
4698 }
4699
4700 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4701 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4702 {
4703         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4704         size_t size;
4705         float newvalue = r_buffermegs[type].value;
4706
4707         // increase the cvar if we have to (but only if we already have a mem)
4708         if (mustgrow && mem)
4709                 newvalue *= 2.0f;
4710         newvalue = bound(0.25f, newvalue, 256.0f);
4711         while (newvalue * 1024*1024 < minsize)
4712                 newvalue *= 2.0f;
4713
4714         // clamp the cvar to valid range
4715         newvalue = bound(0.25f, newvalue, 256.0f);
4716         if (r_buffermegs[type].value != newvalue)
4717                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4718
4719         // calculate size in bytes
4720         size = (size_t)(newvalue * 1024*1024);
4721         size = bound(131072, size, 256*1024*1024);
4722
4723         // allocate a new buffer if the size is different (purge old one later)
4724         // or if we were told we must grow the buffer
4725         if (!mem || mem->size != size || mustgrow)
4726         {
4727                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4728                 mem->size = size;
4729                 mem->current = 0;
4730                 if (type == R_BUFFERDATA_VERTEX)
4731                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4732                 else if (type == R_BUFFERDATA_INDEX16)
4733                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4734                 else if (type == R_BUFFERDATA_INDEX32)
4735                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4736                 else if (type == R_BUFFERDATA_UNIFORM)
4737                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4738                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4739                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4740         }
4741 }
4742
4743 void R_BufferData_NewFrame(void)
4744 {
4745         int type;
4746         r_bufferdata_buffer_t **p, *mem;
4747         // cycle to the next frame's buffers
4748         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4749         // if we ran out of space on the last time we used these buffers, free the old memory now
4750         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4751         {
4752                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4753                 {
4754                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4755                         // free all but the head buffer, this is how we recycle obsolete
4756                         // buffers after they are no longer in use
4757                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4758                         while (*p)
4759                         {
4760                                 mem = *p;
4761                                 *p = (*p)->purge;
4762                                 if (mem->buffer)
4763                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4764                                 Mem_Free(mem);
4765                         }
4766                         // reset the current offset
4767                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4768                 }
4769         }
4770 }
4771
4772 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4773 {
4774         r_bufferdata_buffer_t *mem;
4775         int offset = 0;
4776         int padsize;
4777
4778         *returnbufferoffset = 0;
4779
4780         // align size to a byte boundary appropriate for the buffer type, this
4781         // makes all allocations have aligned start offsets
4782         if (type == R_BUFFERDATA_UNIFORM)
4783                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4784         else
4785                 padsize = (datasize + 15) & ~15;
4786
4787         // if we ran out of space in this buffer we must allocate a new one
4788         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)
4789                 R_BufferData_Resize(type, true, padsize);
4790
4791         // if the resize did not give us enough memory, fail
4792         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)
4793                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4794
4795         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4796         offset = (int)mem->current;
4797         mem->current += padsize;
4798
4799         // upload the data to the buffer at the chosen offset
4800         if (offset == 0)
4801                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4802         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4803
4804         // count the usage for stats
4805         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4806         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4807
4808         // return the buffer offset
4809         *returnbufferoffset = offset;
4810
4811         return mem->buffer;
4812 }
4813
4814 //==================================================================================
4815
4816 // LordHavoc: animcache originally written by Echon, rewritten since then
4817
4818 /**
4819  * Animation cache prevents re-generating mesh data for an animated model
4820  * multiple times in one frame for lighting, shadowing, reflections, etc.
4821  */
4822
4823 void R_AnimCache_Free(void)
4824 {
4825 }
4826
4827 void R_AnimCache_ClearCache(void)
4828 {
4829         int i;
4830         entity_render_t *ent;
4831
4832         for (i = 0;i < r_refdef.scene.numentities;i++)
4833         {
4834                 ent = r_refdef.scene.entities[i];
4835                 ent->animcache_vertex3f = NULL;
4836                 ent->animcache_vertex3f_vertexbuffer = NULL;
4837                 ent->animcache_vertex3f_bufferoffset = 0;
4838                 ent->animcache_normal3f = NULL;
4839                 ent->animcache_normal3f_vertexbuffer = NULL;
4840                 ent->animcache_normal3f_bufferoffset = 0;
4841                 ent->animcache_svector3f = NULL;
4842                 ent->animcache_svector3f_vertexbuffer = NULL;
4843                 ent->animcache_svector3f_bufferoffset = 0;
4844                 ent->animcache_tvector3f = NULL;
4845                 ent->animcache_tvector3f_vertexbuffer = NULL;
4846                 ent->animcache_tvector3f_bufferoffset = 0;
4847                 ent->animcache_vertexmesh = NULL;
4848                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4849                 ent->animcache_vertexmesh_bufferoffset = 0;
4850                 ent->animcache_skeletaltransform3x4 = NULL;
4851                 ent->animcache_skeletaltransform3x4buffer = NULL;
4852                 ent->animcache_skeletaltransform3x4offset = 0;
4853                 ent->animcache_skeletaltransform3x4size = 0;
4854         }
4855 }
4856
4857 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4858 {
4859         int i;
4860
4861         // check if we need the meshbuffers
4862         if (!vid.useinterleavedarrays)
4863                 return;
4864
4865         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4866                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4867         // TODO: upload vertexbuffer?
4868         if (ent->animcache_vertexmesh)
4869         {
4870                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4871                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4872                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4873                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4874                 for (i = 0;i < numvertices;i++)
4875                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4876                 if (ent->animcache_svector3f)
4877                         for (i = 0;i < numvertices;i++)
4878                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4879                 if (ent->animcache_tvector3f)
4880                         for (i = 0;i < numvertices;i++)
4881                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4882                 if (ent->animcache_normal3f)
4883                         for (i = 0;i < numvertices;i++)
4884                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4885         }
4886 }
4887
4888 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4889 {
4890         dp_model_t *model = ent->model;
4891         int numvertices;
4892
4893         // see if this ent is worth caching
4894         if (!model || !model->Draw || !model->AnimateVertices)
4895                 return false;
4896         // nothing to cache if it contains no animations and has no skeleton
4897         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4898                 return false;
4899         // see if it is already cached for gpuskeletal
4900         if (ent->animcache_skeletaltransform3x4)
4901                 return false;
4902         // see if it is already cached as a mesh
4903         if (ent->animcache_vertex3f)
4904         {
4905                 // check if we need to add normals or tangents
4906                 if (ent->animcache_normal3f)
4907                         wantnormals = false;
4908                 if (ent->animcache_svector3f)
4909                         wanttangents = false;
4910                 if (!wantnormals && !wanttangents)
4911                         return false;
4912         }
4913
4914         // check which kind of cache we need to generate
4915         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4916         {
4917                 // cache the skeleton so the vertex shader can use it
4918                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4919                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4920                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4921                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4922                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4923                 // note: this can fail if the buffer is at the grow limit
4924                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4925                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4926         }
4927         else if (ent->animcache_vertex3f)
4928         {
4929                 // mesh was already cached but we may need to add normals/tangents
4930                 // (this only happens with multiple views, reflections, cameras, etc)
4931                 if (wantnormals || wanttangents)
4932                 {
4933                         numvertices = model->surfmesh.num_vertices;
4934                         if (wantnormals)
4935                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4936                         if (wanttangents)
4937                         {
4938                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4939                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4940                         }
4941                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4942                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4943                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4944                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4945                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4946                 }
4947         }
4948         else
4949         {
4950                 // generate mesh cache
4951                 numvertices = model->surfmesh.num_vertices;
4952                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4953                 if (wantnormals)
4954                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4955                 if (wanttangents)
4956                 {
4957                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4958                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4959                 }
4960                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4961                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4962                 if (wantnormals || wanttangents)
4963                 {
4964                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4965                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4966                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4967                 }
4968                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4969                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4970                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4971         }
4972         return true;
4973 }
4974
4975 void R_AnimCache_CacheVisibleEntities(void)
4976 {
4977         int i;
4978         qboolean wantnormals = true;
4979         qboolean wanttangents = !r_showsurfaces.integer;
4980
4981         switch(vid.renderpath)
4982         {
4983         case RENDERPATH_GL20:
4984         case RENDERPATH_D3D9:
4985         case RENDERPATH_D3D10:
4986         case RENDERPATH_D3D11:
4987         case RENDERPATH_GLES2:
4988                 break;
4989         case RENDERPATH_GL11:
4990         case RENDERPATH_GL13:
4991         case RENDERPATH_GLES1:
4992                 wanttangents = false;
4993                 break;
4994         case RENDERPATH_SOFT:
4995                 break;
4996         }
4997
4998         if (r_shownormals.integer)
4999                 wanttangents = wantnormals = true;
5000
5001         // TODO: thread this
5002         // NOTE: R_PrepareRTLights() also caches entities
5003
5004         for (i = 0;i < r_refdef.scene.numentities;i++)
5005                 if (r_refdef.viewcache.entityvisible[i])
5006                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5007 }
5008
5009 //==================================================================================
5010
5011 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5012 {
5013         int i;
5014         vec3_t eyemins, eyemaxs;
5015         vec3_t boxmins, boxmaxs;
5016         vec3_t start;
5017         vec3_t end;
5018         dp_model_t *model = r_refdef.scene.worldmodel;
5019         static vec3_t positions[] = {
5020                 { 0.5f, 0.5f, 0.5f },
5021                 { 0.0f, 0.0f, 0.0f },
5022                 { 0.0f, 0.0f, 1.0f },
5023                 { 0.0f, 1.0f, 0.0f },
5024                 { 0.0f, 1.0f, 1.0f },
5025                 { 1.0f, 0.0f, 0.0f },
5026                 { 1.0f, 0.0f, 1.0f },
5027                 { 1.0f, 1.0f, 0.0f },
5028                 { 1.0f, 1.0f, 1.0f },
5029         };
5030
5031         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5032         if (numsamples < 0)
5033                 return true;
5034
5035         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5036         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5037                 return true;
5038
5039         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5040                 return true;
5041
5042         // expand the eye box a little
5043         eyemins[0] = eye[0] - eyejitter;
5044         eyemaxs[0] = eye[0] + eyejitter;
5045         eyemins[1] = eye[1] - eyejitter;
5046         eyemaxs[1] = eye[1] + eyejitter;
5047         eyemins[2] = eye[2] - eyejitter;
5048         eyemaxs[2] = eye[2] + eyejitter;
5049         // expand the box a little
5050         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5051         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5052         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5053         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5054         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5055         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5056
5057         // return true if eye overlaps enlarged box
5058         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5059                 return true;
5060
5061         // try specific positions in the box first - note that these can be cached
5062         if (r_cullentities_trace_entityocclusion.integer)
5063         {
5064                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5065                 {
5066                         VectorCopy(eye, start);
5067                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5068                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5069                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5070                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5071                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5072                         // not picky - if the trace ended anywhere in the box we're good
5073                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5074                                 return true;
5075                 }
5076         }
5077         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5078                 return true;
5079
5080         // try various random positions
5081         for (i = 0; i < numsamples; i++)
5082         {
5083                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5084                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5085                 if (r_cullentities_trace_entityocclusion.integer)
5086                 {
5087                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5088                         // not picky - if the trace ended anywhere in the box we're good
5089                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5090                                 return true;
5091                 }
5092                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5093                         return true;
5094         }
5095
5096         return false;
5097 }
5098
5099
5100 static void R_View_UpdateEntityVisible (void)
5101 {
5102         int i;
5103         int renderimask;
5104         int samples;
5105         entity_render_t *ent;
5106
5107         if (r_refdef.envmap || r_fb.water.hideplayer)
5108                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5109         else if (chase_active.integer || r_fb.water.renderingscene)
5110                 renderimask = RENDER_VIEWMODEL;
5111         else
5112                 renderimask = RENDER_EXTERIORMODEL;
5113         if (!r_drawviewmodel.integer)
5114                 renderimask |= RENDER_VIEWMODEL;
5115         if (!r_drawexteriormodel.integer)
5116                 renderimask |= RENDER_EXTERIORMODEL;
5117         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5118         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5119         {
5120                 // worldmodel can check visibility
5121                 for (i = 0;i < r_refdef.scene.numentities;i++)
5122                 {
5123                         ent = r_refdef.scene.entities[i];
5124                         if (!(ent->flags & renderimask))
5125                         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)))
5126                         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))
5127                                 r_refdef.viewcache.entityvisible[i] = true;
5128                 }
5129         }
5130         else
5131         {
5132                 // no worldmodel or it can't check visibility
5133                 for (i = 0;i < r_refdef.scene.numentities;i++)
5134                 {
5135                         ent = r_refdef.scene.entities[i];
5136                         if (!(ent->flags & renderimask))
5137                         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)))
5138                                 r_refdef.viewcache.entityvisible[i] = true;
5139                 }
5140         }
5141         if (r_cullentities_trace.integer)
5142         {
5143                 for (i = 0;i < r_refdef.scene.numentities;i++)
5144                 {
5145                         if (!r_refdef.viewcache.entityvisible[i])
5146                                 continue;
5147                         ent = r_refdef.scene.entities[i];
5148                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5149                         {
5150                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5151                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5152                                         ent->last_trace_visibility = realtime;
5153                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5154                                         r_refdef.viewcache.entityvisible[i] = 0;
5155                         }
5156                 }
5157         }
5158 }
5159
5160 /// only used if skyrendermasked, and normally returns false
5161 static int R_DrawBrushModelsSky (void)
5162 {
5163         int i, sky;
5164         entity_render_t *ent;
5165
5166         sky = false;
5167         for (i = 0;i < r_refdef.scene.numentities;i++)
5168         {
5169                 if (!r_refdef.viewcache.entityvisible[i])
5170                         continue;
5171                 ent = r_refdef.scene.entities[i];
5172                 if (!ent->model || !ent->model->DrawSky)
5173                         continue;
5174                 ent->model->DrawSky(ent);
5175                 sky = true;
5176         }
5177         return sky;
5178 }
5179
5180 static void R_DrawNoModel(entity_render_t *ent);
5181 static void R_DrawModels(void)
5182 {
5183         int i;
5184         entity_render_t *ent;
5185
5186         for (i = 0;i < r_refdef.scene.numentities;i++)
5187         {
5188                 if (!r_refdef.viewcache.entityvisible[i])
5189                         continue;
5190                 ent = r_refdef.scene.entities[i];
5191                 r_refdef.stats[r_stat_entities]++;
5192                 /*
5193                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5194                 {
5195                         vec3_t f, l, u, o;
5196                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5197                         Con_Printf("R_DrawModels\n");
5198                         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]);
5199                         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);
5200                         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);
5201                 }
5202                 */
5203                 if (ent->model && ent->model->Draw != NULL)
5204                         ent->model->Draw(ent);
5205                 else
5206                         R_DrawNoModel(ent);
5207         }
5208 }
5209
5210 static void R_DrawModelsDepth(void)
5211 {
5212         int i;
5213         entity_render_t *ent;
5214
5215         for (i = 0;i < r_refdef.scene.numentities;i++)
5216         {
5217                 if (!r_refdef.viewcache.entityvisible[i])
5218                         continue;
5219                 ent = r_refdef.scene.entities[i];
5220                 if (ent->model && ent->model->DrawDepth != NULL)
5221                         ent->model->DrawDepth(ent);
5222         }
5223 }
5224
5225 static void R_DrawModelsDebug(void)
5226 {
5227         int i;
5228         entity_render_t *ent;
5229
5230         for (i = 0;i < r_refdef.scene.numentities;i++)
5231         {
5232                 if (!r_refdef.viewcache.entityvisible[i])
5233                         continue;
5234                 ent = r_refdef.scene.entities[i];
5235                 if (ent->model && ent->model->DrawDebug != NULL)
5236                         ent->model->DrawDebug(ent);
5237         }
5238 }
5239
5240 static void R_DrawModelsAddWaterPlanes(void)
5241 {
5242         int i;
5243         entity_render_t *ent;
5244
5245         for (i = 0;i < r_refdef.scene.numentities;i++)
5246         {
5247                 if (!r_refdef.viewcache.entityvisible[i])
5248                         continue;
5249                 ent = r_refdef.scene.entities[i];
5250                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5251                         ent->model->DrawAddWaterPlanes(ent);
5252         }
5253 }
5254
5255 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}};
5256
5257 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5258 {
5259         if (r_hdr_irisadaptation.integer)
5260         {
5261                 vec3_t p;
5262                 vec3_t ambient;
5263                 vec3_t diffuse;
5264                 vec3_t diffusenormal;
5265                 vec3_t forward;
5266                 vec_t brightness = 0.0f;
5267                 vec_t goal;
5268                 vec_t current;
5269                 vec_t d;
5270                 int c;
5271                 VectorCopy(r_refdef.view.forward, forward);
5272                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5273                 {
5274                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5275                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5276                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5277                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5278                         d = DotProduct(forward, diffusenormal);
5279                         brightness += VectorLength(ambient);
5280                         if (d > 0)
5281                                 brightness += d * VectorLength(diffuse);
5282                 }
5283                 brightness *= 1.0f / c;
5284                 brightness += 0.00001f; // make sure it's never zero
5285                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5286                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5287                 current = r_hdr_irisadaptation_value.value;
5288                 if (current < goal)
5289                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5290                 else if (current > goal)
5291                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5292                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5293                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5294         }
5295         else if (r_hdr_irisadaptation_value.value != 1.0f)
5296                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5297 }
5298
5299 static void R_View_SetFrustum(const int *scissor)
5300 {
5301         int i;
5302         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5303         vec3_t forward, left, up, origin, v;
5304
5305         if(scissor)
5306         {
5307                 // flipped x coordinates (because x points left here)
5308                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5309                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5310
5311                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5312                 switch(vid.renderpath)
5313                 {
5314                         case RENDERPATH_D3D9:
5315                         case RENDERPATH_D3D10:
5316                         case RENDERPATH_D3D11:
5317                                 // non-flipped y coordinates
5318                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5319                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5320                                 break;
5321                         case RENDERPATH_SOFT:
5322                         case RENDERPATH_GL11:
5323                         case RENDERPATH_GL13:
5324                         case RENDERPATH_GL20:
5325                         case RENDERPATH_GLES1:
5326                         case RENDERPATH_GLES2:
5327                                 // non-flipped y coordinates
5328                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5329                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5330                                 break;
5331                 }
5332         }
5333
5334         // we can't trust r_refdef.view.forward and friends in reflected scenes
5335         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5336
5337 #if 0
5338         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5339         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5340         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5341         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5342         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5343         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5344         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5345         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5346         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5347         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5348         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5349         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5350 #endif
5351
5352 #if 0
5353         zNear = r_refdef.nearclip;
5354         nudge = 1.0 - 1.0 / (1<<23);
5355         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5356         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5357         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5358         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5359         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5360         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5361         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5362         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5363 #endif
5364
5365
5366
5367 #if 0
5368         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5369         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5370         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5371         r_refdef.view.frustum[0].dist = m[15] - m[12];
5372
5373         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5374         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5375         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5376         r_refdef.view.frustum[1].dist = m[15] + m[12];
5377
5378         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5379         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5380         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5381         r_refdef.view.frustum[2].dist = m[15] - m[13];
5382
5383         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5384         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5385         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5386         r_refdef.view.frustum[3].dist = m[15] + m[13];
5387
5388         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5389         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5390         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5391         r_refdef.view.frustum[4].dist = m[15] - m[14];
5392
5393         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5394         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5395         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5396         r_refdef.view.frustum[5].dist = m[15] + m[14];
5397 #endif
5398
5399         if (r_refdef.view.useperspective)
5400         {
5401                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5402                 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]);
5403                 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]);
5404                 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]);
5405                 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]);
5406
5407                 // then the normals from the corners relative to origin
5408                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5409                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5410                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5411                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5412
5413                 // in a NORMAL view, forward cross left == up
5414                 // in a REFLECTED view, forward cross left == down
5415                 // so our cross products above need to be adjusted for a left handed coordinate system
5416                 CrossProduct(forward, left, v);
5417                 if(DotProduct(v, up) < 0)
5418                 {
5419                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5420                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5421                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5422                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5423                 }
5424
5425                 // Leaving those out was a mistake, those were in the old code, and they
5426                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5427                 // I couldn't reproduce it after adding those normalizations. --blub
5428                 VectorNormalize(r_refdef.view.frustum[0].normal);
5429                 VectorNormalize(r_refdef.view.frustum[1].normal);
5430                 VectorNormalize(r_refdef.view.frustum[2].normal);
5431                 VectorNormalize(r_refdef.view.frustum[3].normal);
5432
5433                 // make the corners absolute
5434                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5435                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5436                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5437                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5438
5439                 // one more normal
5440                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5441
5442                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5443                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5444                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5445                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5446                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5447         }
5448         else
5449         {
5450                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5451                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5452                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5453                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5454                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5455                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5456                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5457                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5458                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5459                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5460         }
5461         r_refdef.view.numfrustumplanes = 5;
5462
5463         if (r_refdef.view.useclipplane)
5464         {
5465                 r_refdef.view.numfrustumplanes = 6;
5466                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5467         }
5468
5469         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5470                 PlaneClassify(r_refdef.view.frustum + i);
5471
5472         // LordHavoc: note to all quake engine coders, Quake had a special case
5473         // for 90 degrees which assumed a square view (wrong), so I removed it,
5474         // Quake2 has it disabled as well.
5475
5476         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5477         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5478         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5479         //PlaneClassify(&frustum[0]);
5480
5481         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5482         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5483         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5484         //PlaneClassify(&frustum[1]);
5485
5486         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5487         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5488         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5489         //PlaneClassify(&frustum[2]);
5490
5491         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5492         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5493         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5494         //PlaneClassify(&frustum[3]);
5495
5496         // nearclip plane
5497         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5498         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5499         //PlaneClassify(&frustum[4]);
5500 }
5501
5502 static void R_View_UpdateWithScissor(const int *myscissor)
5503 {
5504         R_Main_ResizeViewCache();
5505         R_View_SetFrustum(myscissor);
5506         R_View_WorldVisibility(r_refdef.view.useclipplane);
5507         R_View_UpdateEntityVisible();
5508 }
5509
5510 static void R_View_Update(void)
5511 {
5512         R_Main_ResizeViewCache();
5513         R_View_SetFrustum(NULL);
5514         R_View_WorldVisibility(r_refdef.view.useclipplane);
5515         R_View_UpdateEntityVisible();
5516 }
5517
5518 float viewscalefpsadjusted = 1.0f;
5519
5520 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5521 {
5522         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5523         scale = bound(0.03125f, scale, 1.0f);
5524         *outwidth = (int)ceil(width * scale);
5525         *outheight = (int)ceil(height * scale);
5526 }
5527
5528 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5529 {
5530         const float *customclipplane = NULL;
5531         float plane[4];
5532         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5533         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5534         {
5535                 // LordHavoc: couldn't figure out how to make this approach the
5536                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5537                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5538                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5539                         dist = r_refdef.view.clipplane.dist;
5540                 plane[0] = r_refdef.view.clipplane.normal[0];
5541                 plane[1] = r_refdef.view.clipplane.normal[1];
5542                 plane[2] = r_refdef.view.clipplane.normal[2];
5543                 plane[3] = -dist;
5544                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5545         }
5546
5547         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5548         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5549
5550         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5551         if (!r_refdef.view.useperspective)
5552                 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);
5553         else if (vid.stencil && r_useinfinitefarclip.integer)
5554                 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);
5555         else
5556                 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);
5557         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5558         R_SetViewport(&r_refdef.view.viewport);
5559         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5560         {
5561                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5562                 float screenplane[4];
5563                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5564                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5565                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5566                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5567                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5568         }
5569 }
5570
5571 void R_EntityMatrix(const matrix4x4_t *matrix)
5572 {
5573         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5574         {
5575                 gl_modelmatrixchanged = false;
5576                 gl_modelmatrix = *matrix;
5577                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5578                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5579                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5580                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5581                 CHECKGLERROR
5582                 switch(vid.renderpath)
5583                 {
5584                 case RENDERPATH_D3D9:
5585 #ifdef SUPPORTD3D
5586                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5587                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5588 #endif
5589                         break;
5590                 case RENDERPATH_D3D10:
5591                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5592                         break;
5593                 case RENDERPATH_D3D11:
5594                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5595                         break;
5596                 case RENDERPATH_GL11:
5597                 case RENDERPATH_GL13:
5598                 case RENDERPATH_GLES1:
5599 #ifndef USE_GLES2
5600                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5601 #endif
5602                         break;
5603                 case RENDERPATH_SOFT:
5604                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5605                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5606                         break;
5607                 case RENDERPATH_GL20:
5608                 case RENDERPATH_GLES2:
5609                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5610                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5611                         break;
5612                 }
5613         }
5614 }
5615
5616 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5617 {
5618         r_viewport_t viewport;
5619
5620         CHECKGLERROR
5621
5622         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5623         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);
5624         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5625         R_SetViewport(&viewport);
5626         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5627         GL_Color(1, 1, 1, 1);
5628         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5629         GL_BlendFunc(GL_ONE, GL_ZERO);
5630         GL_ScissorTest(false);
5631         GL_DepthMask(false);
5632         GL_DepthRange(0, 1);
5633         GL_DepthTest(false);
5634         GL_DepthFunc(GL_LEQUAL);
5635         R_EntityMatrix(&identitymatrix);
5636         R_Mesh_ResetTextureState();
5637         GL_PolygonOffset(0, 0);
5638         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5639         switch(vid.renderpath)
5640         {
5641         case RENDERPATH_GL11:
5642         case RENDERPATH_GL13:
5643         case RENDERPATH_GL20:
5644         case RENDERPATH_GLES1:
5645         case RENDERPATH_GLES2:
5646                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5647                 break;
5648         case RENDERPATH_D3D9:
5649         case RENDERPATH_D3D10:
5650         case RENDERPATH_D3D11:
5651         case RENDERPATH_SOFT:
5652                 break;
5653         }
5654         GL_CullFace(GL_NONE);
5655
5656         CHECKGLERROR
5657 }
5658
5659 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5660 {
5661         DrawQ_Finish();
5662
5663         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5664 }
5665
5666 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5667 {
5668         DrawQ_Finish();
5669
5670         R_SetupView(true, fbo, depthtexture, colortexture);
5671         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5672         GL_Color(1, 1, 1, 1);
5673         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5674         GL_BlendFunc(GL_ONE, GL_ZERO);
5675         GL_ScissorTest(true);
5676         GL_DepthMask(true);
5677         GL_DepthRange(0, 1);
5678         GL_DepthTest(true);
5679         GL_DepthFunc(GL_LEQUAL);
5680         R_EntityMatrix(&identitymatrix);
5681         R_Mesh_ResetTextureState();
5682         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5683         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5684         switch(vid.renderpath)
5685         {
5686         case RENDERPATH_GL11:
5687         case RENDERPATH_GL13:
5688         case RENDERPATH_GL20:
5689         case RENDERPATH_GLES1:
5690         case RENDERPATH_GLES2:
5691                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5692                 break;
5693         case RENDERPATH_D3D9:
5694         case RENDERPATH_D3D10:
5695         case RENDERPATH_D3D11:
5696         case RENDERPATH_SOFT:
5697                 break;
5698         }
5699         GL_CullFace(r_refdef.view.cullface_back);
5700 }
5701
5702 /*
5703 ================
5704 R_RenderView_UpdateViewVectors
5705 ================
5706 */
5707 void R_RenderView_UpdateViewVectors(void)
5708 {
5709         // break apart the view matrix into vectors for various purposes
5710         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5711         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5712         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5713         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5714         // make an inverted copy of the view matrix for tracking sprites
5715         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5716 }
5717
5718 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5719 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5720
5721 static void R_Water_StartFrame(void)
5722 {
5723         int i;
5724         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5725         r_waterstate_waterplane_t *p;
5726         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;
5727
5728         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5729                 return;
5730
5731         switch(vid.renderpath)
5732         {
5733         case RENDERPATH_GL20:
5734         case RENDERPATH_D3D9:
5735         case RENDERPATH_D3D10:
5736         case RENDERPATH_D3D11:
5737         case RENDERPATH_SOFT:
5738         case RENDERPATH_GLES2:
5739                 break;
5740         case RENDERPATH_GL11:
5741         case RENDERPATH_GL13:
5742         case RENDERPATH_GLES1:
5743                 return;
5744         }
5745
5746         // set waterwidth and waterheight to the water resolution that will be
5747         // used (often less than the screen resolution for faster rendering)
5748         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5749
5750         // calculate desired texture sizes
5751         // can't use water if the card does not support the texture size
5752         if (!r_water.integer || r_showsurfaces.integer)
5753                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5754         else if (vid.support.arb_texture_non_power_of_two)
5755         {
5756                 texturewidth = waterwidth;
5757                 textureheight = waterheight;
5758                 camerawidth = waterwidth;
5759                 cameraheight = waterheight;
5760         }
5761         else
5762         {
5763                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5764                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5765                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5766                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5767         }
5768
5769         // allocate textures as needed
5770         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))
5771         {
5772                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5773                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5774                 {
5775                         if (p->texture_refraction)
5776                                 R_FreeTexture(p->texture_refraction);
5777                         p->texture_refraction = NULL;
5778                         if (p->fbo_refraction)
5779                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5780                         p->fbo_refraction = 0;
5781                         if (p->texture_reflection)
5782                                 R_FreeTexture(p->texture_reflection);
5783                         p->texture_reflection = NULL;
5784                         if (p->fbo_reflection)
5785                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5786                         p->fbo_reflection = 0;
5787                         if (p->texture_camera)
5788                                 R_FreeTexture(p->texture_camera);
5789                         p->texture_camera = NULL;
5790                         if (p->fbo_camera)
5791                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5792                         p->fbo_camera = 0;
5793                 }
5794                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5795                 r_fb.water.texturewidth = texturewidth;
5796                 r_fb.water.textureheight = textureheight;
5797                 r_fb.water.camerawidth = camerawidth;
5798                 r_fb.water.cameraheight = cameraheight;
5799         }
5800
5801         if (r_fb.water.texturewidth)
5802         {
5803                 int scaledwidth, scaledheight;
5804
5805                 r_fb.water.enabled = true;
5806
5807                 // water resolution is usually reduced
5808                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5809                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5810                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5811
5812                 // set up variables that will be used in shader setup
5813                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5814                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5815                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5816                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5817         }
5818
5819         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5820         r_fb.water.numwaterplanes = 0;
5821 }
5822
5823 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5824 {
5825         int planeindex, bestplaneindex, vertexindex;
5826         vec3_t mins, maxs, normal, center, v, n;
5827         vec_t planescore, bestplanescore;
5828         mplane_t plane;
5829         r_waterstate_waterplane_t *p;
5830         texture_t *t = R_GetCurrentTexture(surface->texture);
5831
5832         rsurface.texture = t;
5833         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5834         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5835         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5836                 return;
5837         // average the vertex normals, find the surface bounds (after deformvertexes)
5838         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5839         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5840         VectorCopy(n, normal);
5841         VectorCopy(v, mins);
5842         VectorCopy(v, maxs);
5843         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5844         {
5845                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5846                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5847                 VectorAdd(normal, n, normal);
5848                 mins[0] = min(mins[0], v[0]);
5849                 mins[1] = min(mins[1], v[1]);
5850                 mins[2] = min(mins[2], v[2]);
5851                 maxs[0] = max(maxs[0], v[0]);
5852                 maxs[1] = max(maxs[1], v[1]);
5853                 maxs[2] = max(maxs[2], v[2]);
5854         }
5855         VectorNormalize(normal);
5856         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5857
5858         VectorCopy(normal, plane.normal);
5859         VectorNormalize(plane.normal);
5860         plane.dist = DotProduct(center, plane.normal);
5861         PlaneClassify(&plane);
5862         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5863         {
5864                 // skip backfaces (except if nocullface is set)
5865 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5866 //                      return;
5867                 VectorNegate(plane.normal, plane.normal);
5868                 plane.dist *= -1;
5869                 PlaneClassify(&plane);
5870         }
5871
5872
5873         // find a matching plane if there is one
5874         bestplaneindex = -1;
5875         bestplanescore = 1048576.0f;
5876         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5877         {
5878                 if(p->camera_entity == t->camera_entity)
5879                 {
5880                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5881                         if (bestplaneindex < 0 || bestplanescore > planescore)
5882                         {
5883                                 bestplaneindex = planeindex;
5884                                 bestplanescore = planescore;
5885                         }
5886                 }
5887         }
5888         planeindex = bestplaneindex;
5889
5890         // if this surface does not fit any known plane rendered this frame, add one
5891         if (planeindex < 0 || bestplanescore > 0.001f)
5892         {
5893                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5894                 {
5895                         // store the new plane
5896                         planeindex = r_fb.water.numwaterplanes++;
5897                         p = r_fb.water.waterplanes + planeindex;
5898                         p->plane = plane;
5899                         // clear materialflags and pvs
5900                         p->materialflags = 0;
5901                         p->pvsvalid = false;
5902                         p->camera_entity = t->camera_entity;
5903                         VectorCopy(mins, p->mins);
5904                         VectorCopy(maxs, p->maxs);
5905                 }
5906                 else
5907                 {
5908                         // We're totally screwed.
5909                         return;
5910                 }
5911         }
5912         else
5913         {
5914                 // merge mins/maxs when we're adding this surface to the plane
5915                 p = r_fb.water.waterplanes + planeindex;
5916                 p->mins[0] = min(p->mins[0], mins[0]);
5917                 p->mins[1] = min(p->mins[1], mins[1]);
5918                 p->mins[2] = min(p->mins[2], mins[2]);
5919                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5920                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5921                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5922         }
5923         // merge this surface's materialflags into the waterplane
5924         p->materialflags |= t->currentmaterialflags;
5925         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5926         {
5927                 // merge this surface's PVS into the waterplane
5928                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5929                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5930                 {
5931                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5932                         p->pvsvalid = true;
5933                 }
5934         }
5935 }
5936
5937 extern cvar_t r_drawparticles;
5938 extern cvar_t r_drawdecals;
5939
5940 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5941 {
5942         int myscissor[4];
5943         r_refdef_view_t originalview;
5944         r_refdef_view_t myview;
5945         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;
5946         r_waterstate_waterplane_t *p;
5947         vec3_t visorigin;
5948         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;
5949         char vabuf[1024];
5950
5951         originalview = r_refdef.view;
5952
5953         // lowquality hack, temporarily shut down some cvars and restore afterwards
5954         qualityreduction = r_water_lowquality.integer;
5955         if (qualityreduction > 0)
5956         {
5957                 if (qualityreduction >= 1)
5958                 {
5959                         old_r_shadows = r_shadows.integer;
5960                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5961                         old_r_dlight = r_shadow_realtime_dlight.integer;
5962                         Cvar_SetValueQuick(&r_shadows, 0);
5963                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5964                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5965                 }
5966                 if (qualityreduction >= 2)
5967                 {
5968                         old_r_dynamic = r_dynamic.integer;
5969                         old_r_particles = r_drawparticles.integer;
5970                         old_r_decals = r_drawdecals.integer;
5971                         Cvar_SetValueQuick(&r_dynamic, 0);
5972                         Cvar_SetValueQuick(&r_drawparticles, 0);
5973                         Cvar_SetValueQuick(&r_drawdecals, 0);
5974                 }
5975         }
5976
5977         // make sure enough textures are allocated
5978         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5979         {
5980                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
5981                         continue;
5982                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5983                 {
5984                         if (!p->texture_refraction)
5985                                 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);
5986                         if (!p->texture_refraction)
5987                                 goto error;
5988                         if (usewaterfbo)
5989                         {
5990                                 if (r_fb.water.depthtexture == NULL)
5991                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5992                                 if (p->fbo_refraction == 0)
5993                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5994                         }
5995                 }
5996                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5997                 {
5998                         if (!p->texture_camera)
5999                                 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);
6000                         if (!p->texture_camera)
6001                                 goto error;
6002                         if (usewaterfbo)
6003                         {
6004                                 if (r_fb.water.depthtexture == NULL)
6005                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6006                                 if (p->fbo_camera == 0)
6007                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6008                         }
6009                 }
6010
6011                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6012                 {
6013                         if (!p->texture_reflection)
6014                                 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);
6015                         if (!p->texture_reflection)
6016                                 goto error;
6017                         if (usewaterfbo)
6018                         {
6019                                 if (r_fb.water.depthtexture == NULL)
6020                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6021                                 if (p->fbo_reflection == 0)
6022                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6023                         }
6024                 }
6025         }
6026
6027         // render views
6028         r_refdef.view = originalview;
6029         r_refdef.view.showdebug = false;
6030         r_refdef.view.width = r_fb.water.waterwidth;
6031         r_refdef.view.height = r_fb.water.waterheight;
6032         r_refdef.view.useclipplane = true;
6033         myview = r_refdef.view;
6034         r_fb.water.renderingscene = true;
6035         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6036         {
6037                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6038                         continue;
6039                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6040                 {
6041                         r_refdef.view = myview;
6042                         if(r_water_scissormode.integer)
6043                         {
6044                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6045                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6046                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6047                         }
6048
6049                         // render reflected scene and copy into texture
6050                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6051                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6052                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6053                         r_refdef.view.clipplane = p->plane;
6054                         // reverse the cullface settings for this render
6055                         r_refdef.view.cullface_front = GL_FRONT;
6056                         r_refdef.view.cullface_back = GL_BACK;
6057                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6058                         {
6059                                 r_refdef.view.usecustompvs = true;
6060                                 if (p->pvsvalid)
6061                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6062                                 else
6063                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6064                         }
6065
6066                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6067                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6068                         R_ClearScreen(r_refdef.fogenabled);
6069                         if(r_water_scissormode.integer & 2)
6070                                 R_View_UpdateWithScissor(myscissor);
6071                         else
6072                                 R_View_Update();
6073                         R_AnimCache_CacheVisibleEntities();
6074                         if(r_water_scissormode.integer & 1)
6075                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6076                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6077
6078                         if (!p->fbo_reflection)
6079                                 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);
6080                         r_fb.water.hideplayer = false;
6081                 }
6082
6083                 // render the normal view scene and copy into texture
6084                 // (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)
6085                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6086                 {
6087                         r_refdef.view = myview;
6088                         if(r_water_scissormode.integer)
6089                         {
6090                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6091                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6092                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6093                         }
6094
6095                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6096
6097                         r_refdef.view.clipplane = p->plane;
6098                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6099                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6100
6101                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6102                         {
6103                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6104                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6105                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6106                                 R_RenderView_UpdateViewVectors();
6107                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6108                                 {
6109                                         r_refdef.view.usecustompvs = true;
6110                                         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);
6111                                 }
6112                         }
6113
6114                         PlaneClassify(&r_refdef.view.clipplane);
6115
6116                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6117                         R_ClearScreen(r_refdef.fogenabled);
6118                         if(r_water_scissormode.integer & 2)
6119                                 R_View_UpdateWithScissor(myscissor);
6120                         else
6121                                 R_View_Update();
6122                         R_AnimCache_CacheVisibleEntities();
6123                         if(r_water_scissormode.integer & 1)
6124                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6125                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6126
6127                         if (!p->fbo_refraction)
6128                                 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);
6129                         r_fb.water.hideplayer = false;
6130                 }
6131                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6132                 {
6133                         r_refdef.view = myview;
6134
6135                         r_refdef.view.clipplane = p->plane;
6136                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6137                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6138
6139                         r_refdef.view.width = r_fb.water.camerawidth;
6140                         r_refdef.view.height = r_fb.water.cameraheight;
6141                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6142                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6143                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6144                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6145
6146                         if(p->camera_entity)
6147                         {
6148                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6149                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6150                         }
6151
6152                         // note: all of the view is used for displaying... so
6153                         // there is no use in scissoring
6154
6155                         // reverse the cullface settings for this render
6156                         r_refdef.view.cullface_front = GL_FRONT;
6157                         r_refdef.view.cullface_back = GL_BACK;
6158                         // also reverse the view matrix
6159                         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
6160                         R_RenderView_UpdateViewVectors();
6161                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6162                         {
6163                                 r_refdef.view.usecustompvs = true;
6164                                 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);
6165                         }
6166                         
6167                         // camera needs no clipplane
6168                         r_refdef.view.useclipplane = false;
6169
6170                         PlaneClassify(&r_refdef.view.clipplane);
6171
6172                         r_fb.water.hideplayer = false;
6173
6174                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6175                         R_ClearScreen(r_refdef.fogenabled);
6176                         R_View_Update();
6177                         R_AnimCache_CacheVisibleEntities();
6178                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6179
6180                         if (!p->fbo_camera)
6181                                 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);
6182                         r_fb.water.hideplayer = false;
6183                 }
6184
6185         }
6186         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6187         r_fb.water.renderingscene = false;
6188         r_refdef.view = originalview;
6189         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6190         if (!r_fb.water.depthtexture)
6191                 R_ClearScreen(r_refdef.fogenabled);
6192         R_View_Update();
6193         R_AnimCache_CacheVisibleEntities();
6194         goto finish;
6195 error:
6196         r_refdef.view = originalview;
6197         r_fb.water.renderingscene = false;
6198         Cvar_SetValueQuick(&r_water, 0);
6199         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6200 finish:
6201         // lowquality hack, restore cvars
6202         if (qualityreduction > 0)
6203         {
6204                 if (qualityreduction >= 1)
6205                 {
6206                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6207                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6208                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6209                 }
6210                 if (qualityreduction >= 2)
6211                 {
6212                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6213                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6214                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6215                 }
6216         }
6217 }
6218
6219 static void R_Bloom_StartFrame(void)
6220 {
6221         int i;
6222         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6223         int viewwidth, viewheight;
6224         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6225         textype_t textype = TEXTYPE_COLORBUFFER;
6226
6227         switch (vid.renderpath)
6228         {
6229         case RENDERPATH_GL20:
6230                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6231                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6232                 {
6233                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6234                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6235                 }
6236                 break;
6237         case RENDERPATH_GL11:
6238         case RENDERPATH_GL13:
6239         case RENDERPATH_GLES1:
6240         case RENDERPATH_GLES2:
6241         case RENDERPATH_D3D9:
6242         case RENDERPATH_D3D10:
6243         case RENDERPATH_D3D11:
6244                 r_fb.usedepthtextures = false;
6245                 break;
6246         case RENDERPATH_SOFT:
6247                 r_fb.usedepthtextures = true;
6248                 break;
6249         }
6250
6251         if (r_viewscale_fpsscaling.integer)
6252         {
6253                 double actualframetime;
6254                 double targetframetime;
6255                 double adjust;
6256                 actualframetime = r_refdef.lastdrawscreentime;
6257                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6258                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6259                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6260                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6261                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6262                 viewscalefpsadjusted += adjust;
6263                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6264         }
6265         else
6266                 viewscalefpsadjusted = 1.0f;
6267
6268         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6269
6270         switch(vid.renderpath)
6271         {
6272         case RENDERPATH_GL20:
6273         case RENDERPATH_D3D9:
6274         case RENDERPATH_D3D10:
6275         case RENDERPATH_D3D11:
6276         case RENDERPATH_SOFT:
6277         case RENDERPATH_GLES2:
6278                 break;
6279         case RENDERPATH_GL11:
6280         case RENDERPATH_GL13:
6281         case RENDERPATH_GLES1:
6282                 return;
6283         }
6284
6285         // set bloomwidth and bloomheight to the bloom resolution that will be
6286         // used (often less than the screen resolution for faster rendering)
6287         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6288         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6289         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6290         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6291         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6292
6293         // calculate desired texture sizes
6294         if (vid.support.arb_texture_non_power_of_two)
6295         {
6296                 screentexturewidth = vid.width;
6297                 screentextureheight = vid.height;
6298                 bloomtexturewidth = r_fb.bloomwidth;
6299                 bloomtextureheight = r_fb.bloomheight;
6300         }
6301         else
6302         {
6303                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6304                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6305                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6306                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6307         }
6308
6309         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))
6310         {
6311                 Cvar_SetValueQuick(&r_bloom, 0);
6312                 Cvar_SetValueQuick(&r_motionblur, 0);
6313                 Cvar_SetValueQuick(&r_damageblur, 0);
6314         }
6315
6316         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6317          && !r_bloom.integer
6318          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6319          && !useviewfbo
6320          && r_viewscale.value == 1.0f
6321          && !r_viewscale_fpsscaling.integer)
6322                 screentexturewidth = screentextureheight = 0;
6323         if (!r_bloom.integer)
6324                 bloomtexturewidth = bloomtextureheight = 0;
6325
6326         // allocate textures as needed
6327         if (r_fb.screentexturewidth != screentexturewidth
6328          || r_fb.screentextureheight != screentextureheight
6329          || r_fb.bloomtexturewidth != bloomtexturewidth
6330          || r_fb.bloomtextureheight != bloomtextureheight
6331          || r_fb.textype != textype
6332          || useviewfbo != (r_fb.fbo != 0))
6333         {
6334                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6335                 {
6336                         if (r_fb.bloomtexture[i])
6337                                 R_FreeTexture(r_fb.bloomtexture[i]);
6338                         r_fb.bloomtexture[i] = NULL;
6339
6340                         if (r_fb.bloomfbo[i])
6341                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6342                         r_fb.bloomfbo[i] = 0;
6343                 }
6344
6345                 if (r_fb.fbo)
6346                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6347                 r_fb.fbo = 0;
6348
6349                 if (r_fb.colortexture)
6350                         R_FreeTexture(r_fb.colortexture);
6351                 r_fb.colortexture = NULL;
6352
6353                 if (r_fb.depthtexture)
6354                         R_FreeTexture(r_fb.depthtexture);
6355                 r_fb.depthtexture = NULL;
6356
6357                 if (r_fb.ghosttexture)
6358                         R_FreeTexture(r_fb.ghosttexture);
6359                 r_fb.ghosttexture = NULL;
6360
6361                 r_fb.screentexturewidth = screentexturewidth;
6362                 r_fb.screentextureheight = screentextureheight;
6363                 r_fb.bloomtexturewidth = bloomtexturewidth;
6364                 r_fb.bloomtextureheight = bloomtextureheight;
6365                 r_fb.textype = textype;
6366
6367                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6368                 {
6369                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6370                                 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);
6371                         r_fb.ghosttexture_valid = false;
6372                         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);
6373                         if (useviewfbo)
6374                         {
6375                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6376                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6377                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6378                         }
6379                 }
6380
6381                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6382                 {
6383                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6384                         {
6385                                 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);
6386                                 if (useviewfbo)
6387                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6388                         }
6389                 }
6390         }
6391
6392         // bloom texture is a different resolution
6393         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6394         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6395         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6396         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6397         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6398
6399         // set up a texcoord array for the full resolution screen image
6400         // (we have to keep this around to copy back during final render)
6401         r_fb.screentexcoord2f[0] = 0;
6402         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6403         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6404         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6405         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6406         r_fb.screentexcoord2f[5] = 0;
6407         r_fb.screentexcoord2f[6] = 0;
6408         r_fb.screentexcoord2f[7] = 0;
6409
6410         if(r_fb.fbo) 
6411         {
6412                 for (i = 1;i < 8;i += 2)
6413                 {
6414                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6415                 }
6416         }
6417
6418         // set up a texcoord array for the reduced resolution bloom image
6419         // (which will be additive blended over the screen image)
6420         r_fb.bloomtexcoord2f[0] = 0;
6421         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6422         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6423         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6424         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6425         r_fb.bloomtexcoord2f[5] = 0;
6426         r_fb.bloomtexcoord2f[6] = 0;
6427         r_fb.bloomtexcoord2f[7] = 0;
6428
6429         switch(vid.renderpath)
6430         {
6431         case RENDERPATH_GL11:
6432         case RENDERPATH_GL13:
6433         case RENDERPATH_GL20:
6434         case RENDERPATH_SOFT:
6435         case RENDERPATH_GLES1:
6436         case RENDERPATH_GLES2:
6437                 break;
6438         case RENDERPATH_D3D9:
6439         case RENDERPATH_D3D10:
6440         case RENDERPATH_D3D11:
6441                 for (i = 0;i < 4;i++)
6442                 {
6443                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6444                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6445                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6446                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6447                 }
6448                 break;
6449         }
6450
6451         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6452
6453         if (r_fb.fbo)
6454                 r_refdef.view.clear = true;
6455 }
6456
6457 static void R_Bloom_MakeTexture(void)
6458 {
6459         int x, range, dir;
6460         float xoffset, yoffset, r, brighten;
6461         rtexture_t *intex;
6462         float colorscale = r_bloom_colorscale.value;
6463
6464         r_refdef.stats[r_stat_bloom]++;
6465     
6466 #if 0
6467     // this copy is unnecessary since it happens in R_BlendView already
6468         if (!r_fb.fbo)
6469         {
6470                 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);
6471                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6472         }
6473 #endif
6474
6475         // scale down screen texture to the bloom texture size
6476         CHECKGLERROR
6477         r_fb.bloomindex = 0;
6478         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6479         R_SetViewport(&r_fb.bloomviewport);
6480         GL_CullFace(GL_NONE);
6481         GL_DepthTest(false);
6482         GL_BlendFunc(GL_ONE, GL_ZERO);
6483         GL_Color(colorscale, colorscale, colorscale, 1);
6484         // 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...
6485         switch(vid.renderpath)
6486         {
6487         case RENDERPATH_GL11:
6488         case RENDERPATH_GL13:
6489         case RENDERPATH_GL20:
6490         case RENDERPATH_GLES1:
6491         case RENDERPATH_GLES2:
6492         case RENDERPATH_SOFT:
6493                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6494                 break;
6495         case RENDERPATH_D3D9:
6496         case RENDERPATH_D3D10:
6497         case RENDERPATH_D3D11:
6498                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6499                 break;
6500         }
6501         // TODO: do boxfilter scale-down in shader?
6502         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6503         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6504         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6505
6506         // we now have a properly scaled bloom image
6507         if (!r_fb.bloomfbo[r_fb.bloomindex])
6508         {
6509                 // copy it into the bloom texture
6510                 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);
6511                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6512         }
6513
6514         // multiply bloom image by itself as many times as desired
6515         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6516         {
6517                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6518                 r_fb.bloomindex ^= 1;
6519                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6520                 x *= 2;
6521                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6522                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6523                 {
6524                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6525                         GL_Color(r,r,r,1); // apply fix factor
6526                 }
6527                 else
6528                 {
6529                         if(x <= 2)
6530                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6531                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6532                         GL_Color(1,1,1,1); // no fix factor supported here
6533                 }
6534                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6535                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6536                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6537                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6538
6539                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6540                 {
6541                         // copy the darkened image to a texture
6542                         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);
6543                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6544                 }
6545         }
6546
6547         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6548         brighten = r_bloom_brighten.value;
6549         brighten = sqrt(brighten);
6550         if(range >= 1)
6551                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6552
6553         for (dir = 0;dir < 2;dir++)
6554         {
6555                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6556                 r_fb.bloomindex ^= 1;
6557                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6558                 // blend on at multiple vertical offsets to achieve a vertical blur
6559                 // TODO: do offset blends using GLSL
6560                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6561                 GL_BlendFunc(GL_ONE, GL_ZERO);
6562                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6563                 for (x = -range;x <= range;x++)
6564                 {
6565                         if (!dir){xoffset = 0;yoffset = x;}
6566                         else {xoffset = x;yoffset = 0;}
6567                         xoffset /= (float)r_fb.bloomtexturewidth;
6568                         yoffset /= (float)r_fb.bloomtextureheight;
6569                         // compute a texcoord array with the specified x and y offset
6570                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6571                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6572                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6573                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6574                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6575                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6576                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6577                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6578                         // this r value looks like a 'dot' particle, fading sharply to
6579                         // black at the edges
6580                         // (probably not realistic but looks good enough)
6581                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6582                         //r = brighten/(range*2+1);
6583                         r = brighten / (range * 2 + 1);
6584                         if(range >= 1)
6585                                 r *= (1 - x*x/(float)(range*range));
6586                         GL_Color(r, r, r, 1);
6587                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6588                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6589                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6590                         GL_BlendFunc(GL_ONE, GL_ONE);
6591                 }
6592
6593                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6594                 {
6595                         // copy the vertically or horizontally blurred bloom view to a texture
6596                         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);
6597                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6598                 }
6599         }
6600 }
6601
6602 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6603 {
6604         dpuint64 permutation;
6605         float uservecs[4][4];
6606
6607         R_EntityMatrix(&identitymatrix);
6608
6609         switch (vid.renderpath)
6610         {
6611         case RENDERPATH_GL20:
6612         case RENDERPATH_D3D9:
6613         case RENDERPATH_D3D10:
6614         case RENDERPATH_D3D11:
6615         case RENDERPATH_SOFT:
6616         case RENDERPATH_GLES2:
6617                 permutation =
6618                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6619                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6620                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6621                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6622                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6623
6624                 if (r_fb.colortexture)
6625                 {
6626                         if (!r_fb.fbo)
6627                         {
6628                                 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);
6629                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6630                         }
6631
6632                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6633                         {
6634                                 // declare variables
6635                                 float blur_factor, blur_mouseaccel, blur_velocity;
6636                                 static float blur_average; 
6637                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6638
6639                                 // set a goal for the factoring
6640                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6641                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6642                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6643                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6644                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6645                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6646
6647                                 // from the goal, pick an averaged value between goal and last value
6648                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6649                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6650
6651                                 // enforce minimum amount of blur 
6652                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6653
6654                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6655
6656                                 // calculate values into a standard alpha
6657                                 cl.motionbluralpha = 1 - exp(-
6658                                                 (
6659                                                  (r_motionblur.value * blur_factor / 80)
6660                                                  +
6661                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6662                                                 )
6663                                                 /
6664                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6665                                           );
6666
6667                                 // randomization for the blur value to combat persistent ghosting
6668                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6669                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6670
6671                                 // apply the blur
6672                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6673                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6674                                 {
6675                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6676                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6677                                         switch(vid.renderpath)
6678                                         {
6679                                         case RENDERPATH_GL11:
6680                                         case RENDERPATH_GL13:
6681                                         case RENDERPATH_GL20:
6682                                         case RENDERPATH_GLES1:
6683                                         case RENDERPATH_GLES2:
6684                                         case RENDERPATH_SOFT:
6685                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6686                                                 break;
6687                                         case RENDERPATH_D3D9:
6688                                         case RENDERPATH_D3D10:
6689                                         case RENDERPATH_D3D11:
6690                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6691                                                 break;
6692                                         }
6693                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6694                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6695                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6696                                 }
6697
6698                                 // updates old view angles for next pass
6699                                 VectorCopy(cl.viewangles, blur_oldangles);
6700
6701                                 // copy view into the ghost texture
6702                                 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);
6703                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6704                                 r_fb.ghosttexture_valid = true;
6705                         }
6706                 }
6707                 else
6708                 {
6709                         // no r_fb.colortexture means we're rendering to the real fb
6710                         // we may still have to do view tint...
6711                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6712                         {
6713                                 // apply a color tint to the whole view
6714                                 R_ResetViewRendering2D(0, NULL, NULL);
6715                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6716                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6717                                 R_SetupShader_Generic_NoTexture(false, true);
6718                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6719                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6720                         }
6721                         break; // no screen processing, no bloom, skip it
6722                 }
6723
6724                 if (r_fb.bloomtexture[0])
6725                 {
6726                         // make the bloom texture
6727                         R_Bloom_MakeTexture();
6728                 }
6729
6730 #if _MSC_VER >= 1400
6731 #define sscanf sscanf_s
6732 #endif
6733                 memset(uservecs, 0, sizeof(uservecs));
6734                 if (r_glsl_postprocess_uservec1_enable.integer)
6735                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6736                 if (r_glsl_postprocess_uservec2_enable.integer)
6737                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6738                 if (r_glsl_postprocess_uservec3_enable.integer)
6739                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6740                 if (r_glsl_postprocess_uservec4_enable.integer)
6741                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6742
6743                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6744                 GL_Color(1, 1, 1, 1);
6745                 GL_BlendFunc(GL_ONE, GL_ZERO);
6746
6747                 switch(vid.renderpath)
6748                 {
6749                 case RENDERPATH_GL20:
6750                 case RENDERPATH_GLES2:
6751                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6752                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6753                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6754                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6755                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6756                         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]);
6757                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6758                         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]);
6759                         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]);
6760                         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]);
6761                         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]);
6762                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6763                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6764                         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);
6765                         break;
6766                 case RENDERPATH_D3D9:
6767 #ifdef SUPPORTD3D
6768                         // 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...
6769                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6770                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6771                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6772                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6773                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6774                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6775                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6776                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6777                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6778                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6779                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6780                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6781                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6782                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6783 #endif
6784                         break;
6785                 case RENDERPATH_D3D10:
6786                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6787                         break;
6788                 case RENDERPATH_D3D11:
6789                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6790                         break;
6791                 case RENDERPATH_SOFT:
6792                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6793                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6794                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6795                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6796                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6797                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6798                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6799                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6800                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6801                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6802                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6803                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6804                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6805                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6806                         break;
6807                 default:
6808                         break;
6809                 }
6810                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6811                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6812                 break;
6813         case RENDERPATH_GL11:
6814         case RENDERPATH_GL13:
6815         case RENDERPATH_GLES1:
6816                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6817                 {
6818                         // apply a color tint to the whole view
6819                         R_ResetViewRendering2D(0, NULL, NULL);
6820                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6821                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6822                         R_SetupShader_Generic_NoTexture(false, true);
6823                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6824                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6825                 }
6826                 break;
6827         }
6828 }
6829
6830 matrix4x4_t r_waterscrollmatrix;
6831
6832 void R_UpdateFog(void)
6833 {
6834         // Nehahra fog
6835         if (gamemode == GAME_NEHAHRA)
6836         {
6837                 if (gl_fogenable.integer)
6838                 {
6839                         r_refdef.oldgl_fogenable = true;
6840                         r_refdef.fog_density = gl_fogdensity.value;
6841                         r_refdef.fog_red = gl_fogred.value;
6842                         r_refdef.fog_green = gl_foggreen.value;
6843                         r_refdef.fog_blue = gl_fogblue.value;
6844                         r_refdef.fog_alpha = 1;
6845                         r_refdef.fog_start = 0;
6846                         r_refdef.fog_end = gl_skyclip.value;
6847                         r_refdef.fog_height = 1<<30;
6848                         r_refdef.fog_fadedepth = 128;
6849                 }
6850                 else if (r_refdef.oldgl_fogenable)
6851                 {
6852                         r_refdef.oldgl_fogenable = false;
6853                         r_refdef.fog_density = 0;
6854                         r_refdef.fog_red = 0;
6855                         r_refdef.fog_green = 0;
6856                         r_refdef.fog_blue = 0;
6857                         r_refdef.fog_alpha = 0;
6858                         r_refdef.fog_start = 0;
6859                         r_refdef.fog_end = 0;
6860                         r_refdef.fog_height = 1<<30;
6861                         r_refdef.fog_fadedepth = 128;
6862                 }
6863         }
6864
6865         // fog parms
6866         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6867         r_refdef.fog_start = max(0, r_refdef.fog_start);
6868         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6869
6870         if (r_refdef.fog_density && r_drawfog.integer)
6871         {
6872                 r_refdef.fogenabled = true;
6873                 // this is the point where the fog reaches 0.9986 alpha, which we
6874                 // consider a good enough cutoff point for the texture
6875                 // (0.9986 * 256 == 255.6)
6876                 if (r_fog_exp2.integer)
6877                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6878                 else
6879                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6880                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6881                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6882                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6883                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6884                         R_BuildFogHeightTexture();
6885                 // fog color was already set
6886                 // update the fog texture
6887                 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)
6888                         R_BuildFogTexture();
6889                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6890                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6891         }
6892         else
6893                 r_refdef.fogenabled = false;
6894
6895         // fog color
6896         if (r_refdef.fog_density)
6897         {
6898                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6899                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6900                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6901
6902                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6903                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6904                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6905                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6906
6907                 {
6908                         vec3_t fogvec;
6909                         VectorCopy(r_refdef.fogcolor, fogvec);
6910                         //   color.rgb *= ContrastBoost * SceneBrightness;
6911                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6912                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6913                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6914                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6915                 }
6916         }
6917 }
6918
6919 void R_UpdateVariables(void)
6920 {
6921         R_Textures_Frame();
6922
6923         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6924
6925         r_refdef.farclip = r_farclip_base.value;
6926         if (r_refdef.scene.worldmodel)
6927                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6928         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6929
6930         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6931                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6932         r_refdef.polygonfactor = 0;
6933         r_refdef.polygonoffset = 0;
6934         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6935         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6936
6937         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6938         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6939         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6940         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6941         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6942         if (FAKELIGHT_ENABLED)
6943         {
6944                 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6945         }
6946         else if (r_refdef.scene.worldmodel)
6947         {
6948                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6949         }
6950         if (r_showsurfaces.integer)
6951         {
6952                 r_refdef.scene.rtworld = false;
6953                 r_refdef.scene.rtworldshadows = false;
6954                 r_refdef.scene.rtdlight = false;
6955                 r_refdef.scene.rtdlightshadows = false;
6956                 r_refdef.scene.lightmapintensity = 0;
6957         }
6958
6959         r_gpuskeletal = false;
6960         switch(vid.renderpath)
6961         {
6962         case RENDERPATH_GL20:
6963                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6964         case RENDERPATH_D3D9:
6965         case RENDERPATH_D3D10:
6966         case RENDERPATH_D3D11:
6967         case RENDERPATH_SOFT:
6968         case RENDERPATH_GLES2:
6969                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6970                 {
6971                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6972                         {
6973                                 // build GLSL gamma texture
6974 #define RAMPWIDTH 256
6975                                 unsigned short ramp[RAMPWIDTH * 3];
6976                                 unsigned char rampbgr[RAMPWIDTH][4];
6977                                 int i;
6978
6979                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6980
6981                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6982                                 for(i = 0; i < RAMPWIDTH; ++i)
6983                                 {
6984                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6985                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6986                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6987                                         rampbgr[i][3] = 0;
6988                                 }
6989                                 if (r_texture_gammaramps)
6990                                 {
6991                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6992                                 }
6993                                 else
6994                                 {
6995                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6996                                 }
6997                         }
6998                 }
6999                 else
7000                 {
7001                         // remove GLSL gamma texture
7002                 }
7003                 break;
7004         case RENDERPATH_GL11:
7005         case RENDERPATH_GL13:
7006         case RENDERPATH_GLES1:
7007                 break;
7008         }
7009 }
7010
7011 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7012 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7013 /*
7014 ================
7015 R_SelectScene
7016 ================
7017 */
7018 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7019         if( scenetype != r_currentscenetype ) {
7020                 // store the old scenetype
7021                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7022                 r_currentscenetype = scenetype;
7023                 // move in the new scene
7024                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7025         }
7026 }
7027
7028 /*
7029 ================
7030 R_GetScenePointer
7031 ================
7032 */
7033 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7034 {
7035         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7036         if( scenetype == r_currentscenetype ) {
7037                 return &r_refdef.scene;
7038         } else {
7039                 return &r_scenes_store[ scenetype ];
7040         }
7041 }
7042
7043 static int R_SortEntities_Compare(const void *ap, const void *bp)
7044 {
7045         const entity_render_t *a = *(const entity_render_t **)ap;
7046         const entity_render_t *b = *(const entity_render_t **)bp;
7047
7048         // 1. compare model
7049         if(a->model < b->model)
7050                 return -1;
7051         if(a->model > b->model)
7052                 return +1;
7053
7054         // 2. compare skin
7055         // TODO possibly calculate the REAL skinnum here first using
7056         // skinscenes?
7057         if(a->skinnum < b->skinnum)
7058                 return -1;
7059         if(a->skinnum > b->skinnum)
7060                 return +1;
7061
7062         // everything we compared is equal
7063         return 0;
7064 }
7065 static void R_SortEntities(void)
7066 {
7067         // below or equal 2 ents, sorting never gains anything
7068         if(r_refdef.scene.numentities <= 2)
7069                 return;
7070         // sort
7071         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7072 }
7073
7074 /*
7075 ================
7076 R_RenderView
7077 ================
7078 */
7079 int dpsoftrast_test;
7080 extern cvar_t r_shadow_bouncegrid;
7081 void R_RenderView(void)
7082 {
7083         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7084         int fbo;
7085         rtexture_t *depthtexture;
7086         rtexture_t *colortexture;
7087
7088         dpsoftrast_test = r_test.integer;
7089
7090         if (r_timereport_active)
7091                 R_TimeReport("start");
7092         r_textureframe++; // used only by R_GetCurrentTexture
7093         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
7094
7095         if(R_CompileShader_CheckStaticParms())
7096                 R_GLSL_Restart_f();
7097
7098         if (!r_drawentities.integer)
7099                 r_refdef.scene.numentities = 0;
7100         else if (r_sortentities.integer)
7101                 R_SortEntities();
7102
7103         R_AnimCache_ClearCache();
7104
7105         /* adjust for stereo display */
7106         if(R_Stereo_Active())
7107         {
7108                 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);
7109                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7110         }
7111
7112         if (r_refdef.view.isoverlay)
7113         {
7114                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7115                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7116                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7117                 R_TimeReport("depthclear");
7118
7119                 r_refdef.view.showdebug = false;
7120
7121                 r_fb.water.enabled = false;
7122                 r_fb.water.numwaterplanes = 0;
7123
7124                 R_RenderScene(0, NULL, NULL);
7125
7126                 r_refdef.view.matrix = originalmatrix;
7127
7128                 CHECKGLERROR
7129                 return;
7130         }
7131
7132         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7133         {
7134                 r_refdef.view.matrix = originalmatrix;
7135                 return;
7136         }
7137
7138         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7139
7140         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7141                 // in sRGB fallback, behave similar to true sRGB: convert this
7142                 // value from linear to sRGB
7143                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7144
7145         R_RenderView_UpdateViewVectors();
7146
7147         R_Shadow_UpdateWorldLightSelection();
7148
7149         R_Bloom_StartFrame();
7150
7151         // apply bloom brightness offset
7152         if(r_fb.bloomtexture[0])
7153                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7154
7155         R_Water_StartFrame();
7156
7157         // now we probably have an fbo to render into
7158         fbo = r_fb.fbo;
7159         depthtexture = r_fb.depthtexture;
7160         colortexture = r_fb.colortexture;
7161
7162         CHECKGLERROR
7163         if (r_timereport_active)
7164                 R_TimeReport("viewsetup");
7165
7166         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7167
7168         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7169         {
7170                 R_ClearScreen(r_refdef.fogenabled);
7171                 if (r_timereport_active)
7172                         R_TimeReport("viewclear");
7173         }
7174         r_refdef.view.clear = true;
7175
7176         r_refdef.view.showdebug = true;
7177
7178         R_View_Update();
7179         if (r_timereport_active)
7180                 R_TimeReport("visibility");
7181
7182         R_AnimCache_CacheVisibleEntities();
7183         if (r_timereport_active)
7184                 R_TimeReport("animcache");
7185
7186         R_Shadow_UpdateBounceGridTexture();
7187         if (r_timereport_active && r_shadow_bouncegrid.integer)
7188                 R_TimeReport("bouncegrid");
7189
7190         r_fb.water.numwaterplanes = 0;
7191         if (r_fb.water.enabled)
7192                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7193
7194         R_RenderScene(fbo, depthtexture, colortexture);
7195         r_fb.water.numwaterplanes = 0;
7196
7197         R_BlendView(fbo, depthtexture, colortexture);
7198         if (r_timereport_active)
7199                 R_TimeReport("blendview");
7200
7201         GL_Scissor(0, 0, vid.width, vid.height);
7202         GL_ScissorTest(false);
7203
7204         r_refdef.view.matrix = originalmatrix;
7205
7206         CHECKGLERROR
7207 }
7208
7209 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7210 {
7211         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7212         {
7213                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7214                 if (r_timereport_active)
7215                         R_TimeReport("waterworld");
7216         }
7217
7218         // don't let sound skip if going slow
7219         if (r_refdef.scene.extraupdate)
7220                 S_ExtraUpdate ();
7221
7222         R_DrawModelsAddWaterPlanes();
7223         if (r_timereport_active)
7224                 R_TimeReport("watermodels");
7225
7226         if (r_fb.water.numwaterplanes)
7227         {
7228                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7229                 if (r_timereport_active)
7230                         R_TimeReport("waterscenes");
7231         }
7232 }
7233
7234 extern cvar_t cl_locs_show;
7235 static void R_DrawLocs(void);
7236 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7237 static void R_DrawModelDecals(void);
7238 extern cvar_t cl_decals_newsystem;
7239 extern qboolean r_shadow_usingdeferredprepass;
7240 extern int r_shadow_shadowmapatlas_modelshadows_size;
7241 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7242 {
7243         qboolean shadowmapping = false;
7244
7245         if (r_timereport_active)
7246                 R_TimeReport("beginscene");
7247
7248         r_refdef.stats[r_stat_renders]++;
7249
7250         R_UpdateFog();
7251
7252         // don't let sound skip if going slow
7253         if (r_refdef.scene.extraupdate)
7254                 S_ExtraUpdate ();
7255
7256         R_MeshQueue_BeginScene();
7257
7258         R_SkyStartFrame();
7259
7260         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);
7261
7262         if (r_timereport_active)
7263                 R_TimeReport("skystartframe");
7264
7265         if (cl.csqc_vidvars.drawworld)
7266         {
7267                 // don't let sound skip if going slow
7268                 if (r_refdef.scene.extraupdate)
7269                         S_ExtraUpdate ();
7270
7271                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7272                 {
7273                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7274                         if (r_timereport_active)
7275                                 R_TimeReport("worldsky");
7276                 }
7277
7278                 if (R_DrawBrushModelsSky() && r_timereport_active)
7279                         R_TimeReport("bmodelsky");
7280
7281                 if (skyrendermasked && skyrenderlater)
7282                 {
7283                         // we have to force off the water clipping plane while rendering sky
7284                         R_SetupView(false, fbo, depthtexture, colortexture);
7285                         R_Sky();
7286                         R_SetupView(true, fbo, depthtexture, colortexture);
7287                         if (r_timereport_active)
7288                                 R_TimeReport("sky");
7289                 }
7290         }
7291
7292         R_Shadow_PrepareModelShadows();
7293         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7294         if (r_timereport_active)
7295                 R_TimeReport("preparelights");
7296
7297         // render all the shadowmaps that will be used for this view
7298         shadowmapping = R_Shadow_ShadowMappingEnabled();
7299         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7300         {
7301                 R_Shadow_DrawShadowMaps();
7302                 if (r_timereport_active)
7303                         R_TimeReport("shadowmaps");
7304         }
7305
7306         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7307         if (r_shadow_usingdeferredprepass)
7308                 R_Shadow_DrawPrepass();
7309
7310         // now we begin the forward pass of the view render
7311         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7312         {
7313                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7314                 if (r_timereport_active)
7315                         R_TimeReport("worlddepth");
7316         }
7317         if (r_depthfirst.integer >= 2)
7318         {
7319                 R_DrawModelsDepth();
7320                 if (r_timereport_active)
7321                         R_TimeReport("modeldepth");
7322         }
7323
7324         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7325         {
7326                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7327                 if (r_timereport_active)
7328                         R_TimeReport("world");
7329         }
7330
7331         // don't let sound skip if going slow
7332         if (r_refdef.scene.extraupdate)
7333                 S_ExtraUpdate ();
7334
7335         R_DrawModels();
7336         if (r_timereport_active)
7337                 R_TimeReport("models");
7338
7339         // don't let sound skip if going slow
7340         if (r_refdef.scene.extraupdate)
7341                 S_ExtraUpdate ();
7342
7343         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7344         {
7345                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7346                 R_Shadow_DrawModelShadows();
7347                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7348                 // don't let sound skip if going slow
7349                 if (r_refdef.scene.extraupdate)
7350                         S_ExtraUpdate ();
7351         }
7352
7353         if (!r_shadow_usingdeferredprepass)
7354         {
7355                 R_Shadow_DrawLights();
7356                 if (r_timereport_active)
7357                         R_TimeReport("rtlights");
7358         }
7359
7360         // don't let sound skip if going slow
7361         if (r_refdef.scene.extraupdate)
7362                 S_ExtraUpdate ();
7363
7364         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7365         {
7366                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7367                 R_Shadow_DrawModelShadows();
7368                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7369                 // don't let sound skip if going slow
7370                 if (r_refdef.scene.extraupdate)
7371                         S_ExtraUpdate ();
7372         }
7373
7374         if (cl.csqc_vidvars.drawworld)
7375         {
7376                 if (cl_decals_newsystem.integer)
7377                 {
7378                         R_DrawModelDecals();
7379                         if (r_timereport_active)
7380                                 R_TimeReport("modeldecals");
7381                 }
7382                 else
7383                 {
7384                         R_DrawDecals();
7385                         if (r_timereport_active)
7386                                 R_TimeReport("decals");
7387                 }
7388
7389                 R_DrawParticles();
7390                 if (r_timereport_active)
7391                         R_TimeReport("particles");
7392
7393                 R_DrawExplosions();
7394                 if (r_timereport_active)
7395                         R_TimeReport("explosions");
7396         }
7397
7398         if (cl.csqc_loaded)
7399                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7400
7401         if (r_refdef.view.showdebug)
7402         {
7403                 if (cl_locs_show.integer)
7404                 {
7405                         R_DrawLocs();
7406                         if (r_timereport_active)
7407                                 R_TimeReport("showlocs");
7408                 }
7409
7410                 if (r_drawportals.integer)
7411                 {
7412                         R_DrawPortals();
7413                         if (r_timereport_active)
7414                                 R_TimeReport("portals");
7415                 }
7416
7417                 if (r_showbboxes_client.value > 0)
7418                 {
7419                         R_DrawEntityBBoxes(CLVM_prog);
7420                         if (r_timereport_active)
7421                                 R_TimeReport("clbboxes");
7422                 }
7423                 if (r_showbboxes.value > 0)
7424                 {
7425                         R_DrawEntityBBoxes(SVVM_prog);
7426                         if (r_timereport_active)
7427                                 R_TimeReport("svbboxes");
7428                 }
7429         }
7430
7431         if (r_transparent.integer)
7432         {
7433                 R_MeshQueue_RenderTransparent();
7434                 if (r_timereport_active)
7435                         R_TimeReport("drawtrans");
7436         }
7437
7438         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))
7439         {
7440                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7441                 if (r_timereport_active)
7442                         R_TimeReport("worlddebug");
7443                 R_DrawModelsDebug();
7444                 if (r_timereport_active)
7445                         R_TimeReport("modeldebug");
7446         }
7447
7448         if (cl.csqc_vidvars.drawworld)
7449         {
7450                 R_Shadow_DrawCoronas();
7451                 if (r_timereport_active)
7452                         R_TimeReport("coronas");
7453         }
7454
7455 #if 0
7456         {
7457                 GL_DepthTest(false);
7458                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7459                 GL_Color(1, 1, 1, 1);
7460                 qglBegin(GL_POLYGON);
7461                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7462                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7463                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7464                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7465                 qglEnd();
7466                 qglBegin(GL_POLYGON);
7467                 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]);
7468                 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]);
7469                 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]);
7470                 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]);
7471                 qglEnd();
7472                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7473         }
7474 #endif
7475
7476         // don't let sound skip if going slow
7477         if (r_refdef.scene.extraupdate)
7478                 S_ExtraUpdate ();
7479 }
7480
7481 static const unsigned short bboxelements[36] =
7482 {
7483         5, 1, 3, 5, 3, 7,
7484         6, 2, 0, 6, 0, 4,
7485         7, 3, 2, 7, 2, 6,
7486         4, 0, 1, 4, 1, 5,
7487         4, 5, 7, 4, 7, 6,
7488         1, 0, 2, 1, 2, 3,
7489 };
7490
7491 #define BBOXEDGES 13
7492 static const float bboxedges[BBOXEDGES][6] = 
7493 {
7494         // whole box
7495         { 0, 0, 0, 1, 1, 1 },
7496         // bottom edges
7497         { 0, 0, 0, 0, 1, 0 },
7498         { 0, 0, 0, 1, 0, 0 },
7499         { 0, 1, 0, 1, 1, 0 },
7500         { 1, 0, 0, 1, 1, 0 },
7501         // top edges
7502         { 0, 0, 1, 0, 1, 1 },
7503         { 0, 0, 1, 1, 0, 1 },
7504         { 0, 1, 1, 1, 1, 1 },
7505         { 1, 0, 1, 1, 1, 1 },
7506         // vertical edges
7507         { 0, 0, 0, 0, 0, 1 },
7508         { 1, 0, 0, 1, 0, 1 },
7509         { 0, 1, 0, 0, 1, 1 },
7510         { 1, 1, 0, 1, 1, 1 },
7511 };
7512
7513 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7514 {
7515         int numvertices = BBOXEDGES * 8;
7516         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7517         int numtriangles = BBOXEDGES * 12;
7518         unsigned short elements[BBOXEDGES * 36];
7519         int i, edge;
7520         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7521
7522         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7523
7524         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7525         GL_DepthMask(false);
7526         GL_DepthRange(0, 1);
7527         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7528
7529         for (edge = 0; edge < BBOXEDGES; edge++)
7530         {
7531                 for (i = 0; i < 3; i++)
7532                 {
7533                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7534                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7535                 }
7536                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7537                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7538                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7539                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7540                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7541                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7542                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7543                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7544                 for (i = 0; i < 36; i++)
7545                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7546         }
7547         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7548         if (r_refdef.fogenabled)
7549         {
7550                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7551                 {
7552                         f1 = RSurf_FogVertex(v);
7553                         f2 = 1 - f1;
7554                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7555                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7556                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7557                 }
7558         }
7559         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7560         R_Mesh_ResetTextureState();
7561         R_SetupShader_Generic_NoTexture(false, false);
7562         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7563 }
7564
7565 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7566 {
7567         // hacky overloading of the parameters
7568         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7569         int i;
7570         float color[4];
7571         prvm_edict_t *edict;
7572
7573         GL_CullFace(GL_NONE);
7574         R_SetupShader_Generic_NoTexture(false, false);
7575
7576         for (i = 0;i < numsurfaces;i++)
7577         {
7578                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7579                 switch ((int)PRVM_serveredictfloat(edict, solid))
7580                 {
7581                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7582                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7583                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7584                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7585                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7586                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7587                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7588                 }
7589                 if (prog == CLVM_prog)
7590                         color[3] *= r_showbboxes_client.value;
7591                 else
7592                         color[3] *= r_showbboxes.value;
7593                 color[3] = bound(0, color[3], 1);
7594                 GL_DepthTest(!r_showdisabledepthtest.integer);
7595                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7596         }
7597 }
7598
7599 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7600 {
7601         int i;
7602         prvm_edict_t *edict;
7603         vec3_t center;
7604
7605         if (prog == NULL)
7606                 return;
7607
7608         for (i = 0; i < prog->num_edicts; i++)
7609         {
7610                 edict = PRVM_EDICT_NUM(i);
7611                 if (edict->priv.server->free)
7612                         continue;
7613                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7614                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7615                         continue;
7616                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7617                         continue;
7618                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7619                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7620         }
7621 }
7622
7623 static const int nomodelelement3i[24] =
7624 {
7625         5, 2, 0,
7626         5, 1, 2,
7627         5, 0, 3,
7628         5, 3, 1,
7629         0, 2, 4,
7630         2, 1, 4,
7631         3, 0, 4,
7632         1, 3, 4
7633 };
7634
7635 static const unsigned short nomodelelement3s[24] =
7636 {
7637         5, 2, 0,
7638         5, 1, 2,
7639         5, 0, 3,
7640         5, 3, 1,
7641         0, 2, 4,
7642         2, 1, 4,
7643         3, 0, 4,
7644         1, 3, 4
7645 };
7646
7647 static const float nomodelvertex3f[6*3] =
7648 {
7649         -16,   0,   0,
7650          16,   0,   0,
7651           0, -16,   0,
7652           0,  16,   0,
7653           0,   0, -16,
7654           0,   0,  16
7655 };
7656
7657 static const float nomodelcolor4f[6*4] =
7658 {
7659         0.0f, 0.0f, 0.5f, 1.0f,
7660         0.0f, 0.0f, 0.5f, 1.0f,
7661         0.0f, 0.5f, 0.0f, 1.0f,
7662         0.0f, 0.5f, 0.0f, 1.0f,
7663         0.5f, 0.0f, 0.0f, 1.0f,
7664         0.5f, 0.0f, 0.0f, 1.0f
7665 };
7666
7667 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7668 {
7669         int i;
7670         float f1, f2, *c;
7671         float color4f[6*4];
7672
7673         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);
7674
7675         // this is only called once per entity so numsurfaces is always 1, and
7676         // surfacelist is always {0}, so this code does not handle batches
7677
7678         if (rsurface.ent_flags & RENDER_ADDITIVE)
7679         {
7680                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7681                 GL_DepthMask(false);
7682         }
7683         else if (ent->alpha < 1)
7684         {
7685                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7686                 GL_DepthMask(false);
7687         }
7688         else
7689         {
7690                 GL_BlendFunc(GL_ONE, GL_ZERO);
7691                 GL_DepthMask(true);
7692         }
7693         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7694         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7695         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7696         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7697         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7698         for (i = 0, c = color4f;i < 6;i++, c += 4)
7699         {
7700                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7701                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7702                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7703                 c[3] *= ent->alpha;
7704         }
7705         if (r_refdef.fogenabled)
7706         {
7707                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7708                 {
7709                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7710                         f2 = 1 - f1;
7711                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7712                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7713                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7714                 }
7715         }
7716 //      R_Mesh_ResetTextureState();
7717         R_SetupShader_Generic_NoTexture(false, false);
7718         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7719         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7720 }
7721
7722 void R_DrawNoModel(entity_render_t *ent)
7723 {
7724         vec3_t org;
7725         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7726         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7727                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7728         else
7729                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7730 }
7731
7732 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7733 {
7734         vec3_t right1, right2, diff, normal;
7735
7736         VectorSubtract (org2, org1, normal);
7737
7738         // calculate 'right' vector for start
7739         VectorSubtract (r_refdef.view.origin, org1, diff);
7740         CrossProduct (normal, diff, right1);
7741         VectorNormalize (right1);
7742
7743         // calculate 'right' vector for end
7744         VectorSubtract (r_refdef.view.origin, org2, diff);
7745         CrossProduct (normal, diff, right2);
7746         VectorNormalize (right2);
7747
7748         vert[ 0] = org1[0] + width * right1[0];
7749         vert[ 1] = org1[1] + width * right1[1];
7750         vert[ 2] = org1[2] + width * right1[2];
7751         vert[ 3] = org1[0] - width * right1[0];
7752         vert[ 4] = org1[1] - width * right1[1];
7753         vert[ 5] = org1[2] - width * right1[2];
7754         vert[ 6] = org2[0] - width * right2[0];
7755         vert[ 7] = org2[1] - width * right2[1];
7756         vert[ 8] = org2[2] - width * right2[2];
7757         vert[ 9] = org2[0] + width * right2[0];
7758         vert[10] = org2[1] + width * right2[1];
7759         vert[11] = org2[2] + width * right2[2];
7760 }
7761
7762 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)
7763 {
7764         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7765         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7766         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7767         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7768         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7769         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7770         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7771         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7772         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7773         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7774         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7775         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7776 }
7777
7778 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7779 {
7780         int i;
7781         float *vertex3f;
7782         float v[3];
7783         VectorSet(v, x, y, z);
7784         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7785                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7786                         break;
7787         if (i == mesh->numvertices)
7788         {
7789                 if (mesh->numvertices < mesh->maxvertices)
7790                 {
7791                         VectorCopy(v, vertex3f);
7792                         mesh->numvertices++;
7793                 }
7794                 return mesh->numvertices;
7795         }
7796         else
7797                 return i;
7798 }
7799
7800 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7801 {
7802         int i;
7803         int *e, element[3];
7804         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7805         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7806         e = mesh->element3i + mesh->numtriangles * 3;
7807         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7808         {
7809                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7810                 if (mesh->numtriangles < mesh->maxtriangles)
7811                 {
7812                         *e++ = element[0];
7813                         *e++ = element[1];
7814                         *e++ = element[2];
7815                         mesh->numtriangles++;
7816                 }
7817                 element[1] = element[2];
7818         }
7819 }
7820
7821 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7822 {
7823         int i;
7824         int *e, element[3];
7825         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7826         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7827         e = mesh->element3i + mesh->numtriangles * 3;
7828         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7829         {
7830                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7831                 if (mesh->numtriangles < mesh->maxtriangles)
7832                 {
7833                         *e++ = element[0];
7834                         *e++ = element[1];
7835                         *e++ = element[2];
7836                         mesh->numtriangles++;
7837                 }
7838                 element[1] = element[2];
7839         }
7840 }
7841
7842 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7843 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7844 {
7845         int planenum, planenum2;
7846         int w;
7847         int tempnumpoints;
7848         mplane_t *plane, *plane2;
7849         double maxdist;
7850         double temppoints[2][256*3];
7851         // figure out how large a bounding box we need to properly compute this brush
7852         maxdist = 0;
7853         for (w = 0;w < numplanes;w++)
7854                 maxdist = max(maxdist, fabs(planes[w].dist));
7855         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7856         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7857         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7858         {
7859                 w = 0;
7860                 tempnumpoints = 4;
7861                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7862                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7863                 {
7864                         if (planenum2 == planenum)
7865                                 continue;
7866                         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);
7867                         w = !w;
7868                 }
7869                 if (tempnumpoints < 3)
7870                         continue;
7871                 // generate elements forming a triangle fan for this polygon
7872                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7873         }
7874 }
7875
7876 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)
7877 {
7878         texturelayer_t *layer;
7879         layer = t->currentlayers + t->currentnumlayers++;
7880         layer->type = type;
7881         layer->depthmask = depthmask;
7882         layer->blendfunc1 = blendfunc1;
7883         layer->blendfunc2 = blendfunc2;
7884         layer->texture = texture;
7885         layer->texmatrix = *matrix;
7886         layer->color[0] = r;
7887         layer->color[1] = g;
7888         layer->color[2] = b;
7889         layer->color[3] = a;
7890 }
7891
7892 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7893 {
7894         if(parms[0] == 0 && parms[1] == 0)
7895                 return false;
7896         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7897                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7898                         return false;
7899         return true;
7900 }
7901
7902 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7903 {
7904         double index, f;
7905         index = parms[2] + rsurface.shadertime * parms[3];
7906         index -= floor(index);
7907         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7908         {
7909         default:
7910         case Q3WAVEFUNC_NONE:
7911         case Q3WAVEFUNC_NOISE:
7912         case Q3WAVEFUNC_COUNT:
7913                 f = 0;
7914                 break;
7915         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7916         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7917         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7918         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7919         case Q3WAVEFUNC_TRIANGLE:
7920                 index *= 4;
7921                 f = index - floor(index);
7922                 if (index < 1)
7923                 {
7924                         // f = f;
7925                 }
7926                 else if (index < 2)
7927                         f = 1 - f;
7928                 else if (index < 3)
7929                         f = -f;
7930                 else
7931                         f = -(1 - f);
7932                 break;
7933         }
7934         f = parms[0] + parms[1] * f;
7935         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7936                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7937         return (float) f;
7938 }
7939
7940 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7941 {
7942         int w, h, idx;
7943         float shadertime;
7944         float f;
7945         float offsetd[2];
7946         float tcmat[12];
7947         matrix4x4_t matrix, temp;
7948         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7949         // it's better to have one huge fixup every 9 hours than gradual
7950         // degradation over time which looks consistently bad after many hours.
7951         //
7952         // tcmod scroll in particular suffers from this degradation which can't be
7953         // effectively worked around even with floor() tricks because we don't
7954         // know if tcmod scroll is the last tcmod being applied, and for clampmap
7955         // a workaround involving floor() would be incorrect anyway...
7956         shadertime = rsurface.shadertime;
7957         if (shadertime >= 32768.0f)
7958                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7959         switch(tcmod->tcmod)
7960         {
7961                 case Q3TCMOD_COUNT:
7962                 case Q3TCMOD_NONE:
7963                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7964                                 matrix = r_waterscrollmatrix;
7965                         else
7966                                 matrix = identitymatrix;
7967                         break;
7968                 case Q3TCMOD_ENTITYTRANSLATE:
7969                         // this is used in Q3 to allow the gamecode to control texcoord
7970                         // scrolling on the entity, which is not supported in darkplaces yet.
7971                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7972                         break;
7973                 case Q3TCMOD_ROTATE:
7974                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7975                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7976                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7977                         break;
7978                 case Q3TCMOD_SCALE:
7979                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7980                         break;
7981                 case Q3TCMOD_SCROLL:
7982                         // this particular tcmod is a "bug for bug" compatible one with regards to
7983                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
7984                         // specifically did the wrapping and so we must mimic that...
7985                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7986                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7987                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7988                         break;
7989                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7990                         w = (int) tcmod->parms[0];
7991                         h = (int) tcmod->parms[1];
7992                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7993                         f = f - floor(f);
7994                         idx = (int) floor(f * w * h);
7995                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7996                         break;
7997                 case Q3TCMOD_STRETCH:
7998                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7999                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8000                         break;
8001                 case Q3TCMOD_TRANSFORM:
8002                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8003                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8004                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8005                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8006                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8007                         break;
8008                 case Q3TCMOD_TURBULENT:
8009                         // this is handled in the RSurf_PrepareVertices function
8010                         matrix = identitymatrix;
8011                         break;
8012         }
8013         temp = *texmatrix;
8014         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8015 }
8016
8017 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8018 {
8019         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8020         char name[MAX_QPATH];
8021         skinframe_t *skinframe;
8022         unsigned char pixels[296*194];
8023         strlcpy(cache->name, skinname, sizeof(cache->name));
8024         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8025         if (developer_loading.integer)
8026                 Con_Printf("loading %s\n", name);
8027         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8028         if (!skinframe || !skinframe->base)
8029         {
8030                 unsigned char *f;
8031                 fs_offset_t filesize;
8032                 skinframe = NULL;
8033                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8034                 if (f)
8035                 {
8036                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8037                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8038                         Mem_Free(f);
8039                 }
8040         }
8041         cache->skinframe = skinframe;
8042 }
8043
8044 texture_t *R_GetCurrentTexture(texture_t *t)
8045 {
8046         int i, q;
8047         const entity_render_t *ent = rsurface.entity;
8048         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8049         q3shaderinfo_layer_tcmod_t *tcmod;
8050         float specularscale = 0.0f;
8051
8052         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8053                 return t->currentframe;
8054         t->update_lastrenderframe = r_textureframe;
8055         t->update_lastrenderentity = (void *)ent;
8056
8057         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8058                 t->camera_entity = ent->entitynumber;
8059         else
8060                 t->camera_entity = 0;
8061
8062         // switch to an alternate material if this is a q1bsp animated material
8063         {
8064                 texture_t *texture = t;
8065                 int s = rsurface.ent_skinnum;
8066                 if ((unsigned int)s >= (unsigned int)model->numskins)
8067                         s = 0;
8068                 if (model->skinscenes)
8069                 {
8070                         if (model->skinscenes[s].framecount > 1)
8071                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8072                         else
8073                                 s = model->skinscenes[s].firstframe;
8074                 }
8075                 if (s > 0)
8076                         t = t + s * model->num_surfaces;
8077                 if (t->animated)
8078                 {
8079                         // use an alternate animation if the entity's frame is not 0,
8080                         // and only if the texture has an alternate animation
8081                         if (t->animated == 2) // q2bsp
8082                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8083                         else if (rsurface.ent_alttextures && t->anim_total[1])
8084                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8085                         else
8086                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8087                 }
8088                 texture->currentframe = t;
8089         }
8090
8091         // update currentskinframe to be a qw skin or animation frame
8092         if (rsurface.ent_qwskin >= 0)
8093         {
8094                 i = rsurface.ent_qwskin;
8095                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8096                 {
8097                         r_qwskincache_size = cl.maxclients;
8098                         if (r_qwskincache)
8099                                 Mem_Free(r_qwskincache);
8100                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8101                 }
8102                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8103                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8104                 t->currentskinframe = r_qwskincache[i].skinframe;
8105                 if (t->materialshaderpass && t->currentskinframe == NULL)
8106                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8107         }
8108         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8109                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8110         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8111                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8112
8113         t->currentmaterialflags = t->basematerialflags;
8114         t->currentalpha = rsurface.entity->alpha * t->basealpha;
8115         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8116                 t->currentalpha *= r_wateralpha.value;
8117         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8118                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8119         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8120                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8121
8122         // decide on which type of lighting to use for this surface
8123         if (rsurface.entity->render_modellight_forced)
8124                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8125         if (rsurface.entity->render_rtlight_disabled)
8126                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8127         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8128         {
8129                 // some CUSTOMBLEND blendfuncs are too weird for anything but fullbright rendering, and even then we have to ignore colormod and view colorscale
8130                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NORTLIGHT;
8131                 for (q = 0; q < 3; q++)
8132                 {
8133                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
8134                         t->render_modellight_lightdir[q] = q == 2;
8135                         t->render_modellight_ambient[q] = 1;
8136                         t->render_modellight_diffuse[q] = 0;
8137                         t->render_modellight_specular[q] = 0;
8138                         t->render_lightmap_ambient[q] = 0;
8139                         t->render_lightmap_diffuse[q] = 0;
8140                         t->render_lightmap_specular[q] = 0;
8141                         t->render_rtlight_diffuse[q] = 0;
8142                         t->render_rtlight_specular[q] = 0;
8143                 }
8144         }
8145         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8146         {
8147                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8148                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8149                 for (q = 0; q < 3; q++)
8150                 {
8151                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8152                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8153                         t->render_modellight_lightdir[q] = q == 2;
8154                         t->render_modellight_diffuse[q] = 0;
8155                         t->render_modellight_specular[q] = 0;
8156                         t->render_lightmap_ambient[q] = 0;
8157                         t->render_lightmap_diffuse[q] = 0;
8158                         t->render_lightmap_specular[q] = 0;
8159                         t->render_rtlight_diffuse[q] = 0;
8160                         t->render_rtlight_specular[q] = 0;
8161                 }
8162         }
8163         else if (FAKELIGHT_ENABLED)
8164         {
8165                 // no modellight if using fakelight for the map
8166                 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8167                 for (q = 0; q < 3; q++)
8168                 {
8169                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8170                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8171                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8172                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8173                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8174                         t->render_lightmap_ambient[q] = 0;
8175                         t->render_lightmap_diffuse[q] = 0;
8176                         t->render_lightmap_specular[q] = 0;
8177                         t->render_rtlight_diffuse[q] = 0;
8178                         t->render_rtlight_specular[q] = 0;
8179                 }
8180         }
8181         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8182         {
8183                 // ambient + single direction light (modellight)
8184                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8185                 for (q = 0; q < 3; q++)
8186                 {
8187                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8188                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8189                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8190                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8191                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8192                         t->render_lightmap_ambient[q] = 0;
8193                         t->render_lightmap_diffuse[q] = 0;
8194                         t->render_lightmap_specular[q] = 0;
8195                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8196                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8197                 }
8198         }
8199         else
8200         {
8201                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8202                 for (q = 0; q < 3; q++)
8203                 {
8204                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8205                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q] * r_refdef.view.colorscale;
8206                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8207                         t->render_modellight_diffuse[q] = 0;
8208                         t->render_modellight_specular[q] = 0;
8209                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8210                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8211                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8212                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8213                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8214                 }
8215         }
8216
8217         for (q = 0; q < 3; q++)
8218         {
8219                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8220                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8221         }
8222
8223         if (rsurface.ent_flags & RENDER_ADDITIVE)
8224                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8225         else if (t->currentalpha < 1)
8226                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8227         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8228         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8229                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8230         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8231                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8232         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8233                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8234         if (t->backgroundshaderpass)
8235                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8236         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8237         {
8238                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8239                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8240         }
8241         else
8242                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8243         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8244         {
8245                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8246                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8247         }
8248         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8249                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8250
8251         // there is no tcmod
8252         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8253         {
8254                 t->currenttexmatrix = r_waterscrollmatrix;
8255                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8256         }
8257         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8258         {
8259                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8260                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8261         }
8262
8263         if (t->materialshaderpass)
8264                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8265                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8266
8267         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8268         if (t->currentskinframe->qpixels)
8269                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8270         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8271         if (!t->basetexture)
8272                 t->basetexture = r_texture_notexture;
8273         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8274         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8275         t->nmaptexture = t->currentskinframe->nmap;
8276         if (!t->nmaptexture)
8277                 t->nmaptexture = r_texture_blanknormalmap;
8278         t->glosstexture = r_texture_black;
8279         t->glowtexture = t->currentskinframe->glow;
8280         t->fogtexture = t->currentskinframe->fog;
8281         t->reflectmasktexture = t->currentskinframe->reflect;
8282         if (t->backgroundshaderpass)
8283         {
8284                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8285                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8286                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8287                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8288                 t->backgroundglosstexture = r_texture_black;
8289                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8290                 if (!t->backgroundnmaptexture)
8291                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8292                 // make sure that if glow is going to be used, both textures are not NULL
8293                 if (!t->backgroundglowtexture && t->glowtexture)
8294                         t->backgroundglowtexture = r_texture_black;
8295                 if (!t->glowtexture && t->backgroundglowtexture)
8296                         t->glowtexture = r_texture_black;
8297         }
8298         else
8299         {
8300                 t->backgroundbasetexture = r_texture_white;
8301                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8302                 t->backgroundglosstexture = r_texture_black;
8303                 t->backgroundglowtexture = NULL;
8304         }
8305         t->specularpower = r_shadow_glossexponent.value;
8306         // TODO: store reference values for these in the texture?
8307         if (r_shadow_gloss.integer > 0)
8308         {
8309                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8310                 {
8311                         if (r_shadow_glossintensity.value > 0)
8312                         {
8313                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8314                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8315                                 specularscale = r_shadow_glossintensity.value;
8316                         }
8317                 }
8318                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8319                 {
8320                         t->glosstexture = r_texture_white;
8321                         t->backgroundglosstexture = r_texture_white;
8322                         specularscale = r_shadow_gloss2intensity.value;
8323                         t->specularpower = r_shadow_gloss2exponent.value;
8324                 }
8325         }
8326         specularscale *= t->specularscalemod;
8327         t->specularpower *= t->specularpowermod;
8328
8329         // lightmaps mode looks bad with dlights using actual texturing, so turn
8330         // off the colormap and glossmap, but leave the normalmap on as it still
8331         // accurately represents the shading involved
8332         if (gl_lightmaps.integer)
8333         {
8334                 t->basetexture = r_texture_grey128;
8335                 t->pantstexture = r_texture_black;
8336                 t->shirttexture = r_texture_black;
8337                 if (gl_lightmaps.integer < 2)
8338                         t->nmaptexture = r_texture_blanknormalmap;
8339                 t->glosstexture = r_texture_black;
8340                 t->glowtexture = NULL;
8341                 t->fogtexture = NULL;
8342                 t->reflectmasktexture = NULL;
8343                 t->backgroundbasetexture = NULL;
8344                 if (gl_lightmaps.integer < 2)
8345                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8346                 t->backgroundglosstexture = r_texture_black;
8347                 t->backgroundglowtexture = NULL;
8348                 specularscale = 0;
8349                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8350         }
8351
8352         if (specularscale != 1.0f)
8353         {
8354                 for (q = 0; q < 3; q++)
8355                 {
8356                         t->render_modellight_specular[q] *= specularscale;
8357                         t->render_lightmap_specular[q] *= specularscale;
8358                         t->render_rtlight_specular[q] *= specularscale;
8359                 }
8360         }
8361
8362         t->currentnumlayers = 0;
8363         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8364         {
8365                 int blendfunc1, blendfunc2;
8366                 qboolean depthmask;
8367                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8368                 {
8369                         blendfunc1 = GL_SRC_ALPHA;
8370                         blendfunc2 = GL_ONE;
8371                 }
8372                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8373                 {
8374                         blendfunc1 = GL_SRC_ALPHA;
8375                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8376                 }
8377                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8378                 {
8379                         blendfunc1 = t->customblendfunc[0];
8380                         blendfunc2 = t->customblendfunc[1];
8381                 }
8382                 else
8383                 {
8384                         blendfunc1 = GL_ONE;
8385                         blendfunc2 = GL_ZERO;
8386                 }
8387                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8388                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8389                 {
8390                         // basic lit geometry
8391                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8392                         // add pants/shirt if needed
8393                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8394                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8395                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8396                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8397                 }
8398                 else
8399                 {
8400                         // basic lit geometry
8401                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8402                         // add pants/shirt if needed
8403                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8404                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2]  * t->render_lightmap_diffuse[2], t->currentalpha);
8405                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8406                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8407                         // now add ambient passes if needed
8408                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8409                         {
8410                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha);
8411                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8412                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha);
8413                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8414                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha);
8415                         }
8416                 }
8417                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8418                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha);
8419                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8420                 {
8421                         // if this is opaque use alpha blend which will darken the earlier
8422                         // passes cheaply.
8423                         //
8424                         // if this is an alpha blended material, all the earlier passes
8425                         // were darkened by fog already, so we only need to add the fog
8426                         // color ontop through the fog mask texture
8427                         //
8428                         // if this is an additive blended material, all the earlier passes
8429                         // were darkened by fog already, and we should not add fog color
8430                         // (because the background was not darkened, there is no fog color
8431                         // that was lost behind it).
8432                         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->currentalpha);
8433                 }
8434         }
8435
8436         return t;
8437 }
8438
8439 rsurfacestate_t rsurface;
8440
8441 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8442 {
8443         dp_model_t *model = ent->model;
8444         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8445         //      return;
8446         rsurface.entity = (entity_render_t *)ent;
8447         rsurface.skeleton = ent->skeleton;
8448         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8449         rsurface.ent_skinnum = ent->skinnum;
8450         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;
8451         rsurface.ent_flags = ent->flags;
8452         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8453                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8454         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8455         rsurface.matrix = ent->matrix;
8456         rsurface.inversematrix = ent->inversematrix;
8457         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8458         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8459         R_EntityMatrix(&rsurface.matrix);
8460         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8461         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8462         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8463         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8464         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8465         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8466         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8467         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8468         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8469         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8470         if (ent->model->brush.submodel && !prepass)
8471         {
8472                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8473                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8474         }
8475         // if the animcache code decided it should use the shader path, skip the deform step
8476         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8477         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8478         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8479         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8480         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8481         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8482         {
8483                 if (ent->animcache_vertex3f)
8484                 {
8485                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8486                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8487                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8488                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8489                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8490                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8491                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8492                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8493                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8494                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8495                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8496                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8497                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8498                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8499                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8500                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8501                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8502                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8503                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8504                 }
8505                 else if (wanttangents)
8506                 {
8507                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8508                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8509                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8510                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8511                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8512                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8513                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8514                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8515                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8516                         rsurface.modelvertexmesh = NULL;
8517                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8518                         rsurface.modelvertexmesh_bufferoffset = 0;
8519                         rsurface.modelvertex3f_vertexbuffer = NULL;
8520                         rsurface.modelvertex3f_bufferoffset = 0;
8521                         rsurface.modelvertex3f_vertexbuffer = 0;
8522                         rsurface.modelvertex3f_bufferoffset = 0;
8523                         rsurface.modelsvector3f_vertexbuffer = 0;
8524                         rsurface.modelsvector3f_bufferoffset = 0;
8525                         rsurface.modeltvector3f_vertexbuffer = 0;
8526                         rsurface.modeltvector3f_bufferoffset = 0;
8527                         rsurface.modelnormal3f_vertexbuffer = 0;
8528                         rsurface.modelnormal3f_bufferoffset = 0;
8529                 }
8530                 else if (wantnormals)
8531                 {
8532                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8533                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8534                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8535                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8536                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8537                         rsurface.modelsvector3f = NULL;
8538                         rsurface.modeltvector3f = NULL;
8539                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8540                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8541                         rsurface.modelvertexmesh = NULL;
8542                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8543                         rsurface.modelvertexmesh_bufferoffset = 0;
8544                         rsurface.modelvertex3f_vertexbuffer = NULL;
8545                         rsurface.modelvertex3f_bufferoffset = 0;
8546                         rsurface.modelvertex3f_vertexbuffer = 0;
8547                         rsurface.modelvertex3f_bufferoffset = 0;
8548                         rsurface.modelsvector3f_vertexbuffer = 0;
8549                         rsurface.modelsvector3f_bufferoffset = 0;
8550                         rsurface.modeltvector3f_vertexbuffer = 0;
8551                         rsurface.modeltvector3f_bufferoffset = 0;
8552                         rsurface.modelnormal3f_vertexbuffer = 0;
8553                         rsurface.modelnormal3f_bufferoffset = 0;
8554                 }
8555                 else
8556                 {
8557                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8558                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8559                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8560                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8561                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8562                         rsurface.modelsvector3f = NULL;
8563                         rsurface.modeltvector3f = NULL;
8564                         rsurface.modelnormal3f = NULL;
8565                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8566                         rsurface.modelvertexmesh = NULL;
8567                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8568                         rsurface.modelvertexmesh_bufferoffset = 0;
8569                         rsurface.modelvertex3f_vertexbuffer = NULL;
8570                         rsurface.modelvertex3f_bufferoffset = 0;
8571                         rsurface.modelvertex3f_vertexbuffer = 0;
8572                         rsurface.modelvertex3f_bufferoffset = 0;
8573                         rsurface.modelsvector3f_vertexbuffer = 0;
8574                         rsurface.modelsvector3f_bufferoffset = 0;
8575                         rsurface.modeltvector3f_vertexbuffer = 0;
8576                         rsurface.modeltvector3f_bufferoffset = 0;
8577                         rsurface.modelnormal3f_vertexbuffer = 0;
8578                         rsurface.modelnormal3f_bufferoffset = 0;
8579                 }
8580                 rsurface.modelgeneratedvertex = true;
8581         }
8582         else
8583         {
8584                 if (rsurface.entityskeletaltransform3x4)
8585                 {
8586                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8587                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8588                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8589                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8590                 }
8591                 else
8592                 {
8593                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8594                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8595                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8596                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8597                 }
8598                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8599                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8600                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8601                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8602                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8603                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8604                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8605                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8606                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8607                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8608                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8609                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8610                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8611                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8612                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8613                 rsurface.modelgeneratedvertex = false;
8614         }
8615         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8616         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8617         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8618         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8619         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8620         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8621         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8622         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8623         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8624         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8625         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8626         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8627         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8628         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8629         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8630         rsurface.modelelement3i = model->surfmesh.data_element3i;
8631         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8632         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8633         rsurface.modelelement3s = model->surfmesh.data_element3s;
8634         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8635         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8636         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8637         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8638         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8639         rsurface.modelsurfaces = model->data_surfaces;
8640         rsurface.batchgeneratedvertex = false;
8641         rsurface.batchfirstvertex = 0;
8642         rsurface.batchnumvertices = 0;
8643         rsurface.batchfirsttriangle = 0;
8644         rsurface.batchnumtriangles = 0;
8645         rsurface.batchvertex3f  = NULL;
8646         rsurface.batchvertex3f_vertexbuffer = NULL;
8647         rsurface.batchvertex3f_bufferoffset = 0;
8648         rsurface.batchsvector3f = NULL;
8649         rsurface.batchsvector3f_vertexbuffer = NULL;
8650         rsurface.batchsvector3f_bufferoffset = 0;
8651         rsurface.batchtvector3f = NULL;
8652         rsurface.batchtvector3f_vertexbuffer = NULL;
8653         rsurface.batchtvector3f_bufferoffset = 0;
8654         rsurface.batchnormal3f  = NULL;
8655         rsurface.batchnormal3f_vertexbuffer = NULL;
8656         rsurface.batchnormal3f_bufferoffset = 0;
8657         rsurface.batchlightmapcolor4f = NULL;
8658         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8659         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8660         rsurface.batchtexcoordtexture2f = NULL;
8661         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8662         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8663         rsurface.batchtexcoordlightmap2f = NULL;
8664         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8665         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8666         rsurface.batchskeletalindex4ub = NULL;
8667         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8668         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8669         rsurface.batchskeletalweight4ub = NULL;
8670         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8671         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8672         rsurface.batchvertexmesh = NULL;
8673         rsurface.batchvertexmesh_vertexbuffer = NULL;
8674         rsurface.batchvertexmesh_bufferoffset = 0;
8675         rsurface.batchelement3i = NULL;
8676         rsurface.batchelement3i_indexbuffer = NULL;
8677         rsurface.batchelement3i_bufferoffset = 0;
8678         rsurface.batchelement3s = NULL;
8679         rsurface.batchelement3s_indexbuffer = NULL;
8680         rsurface.batchelement3s_bufferoffset = 0;
8681         rsurface.passcolor4f = NULL;
8682         rsurface.passcolor4f_vertexbuffer = NULL;
8683         rsurface.passcolor4f_bufferoffset = 0;
8684         rsurface.forcecurrenttextureupdate = false;
8685 }
8686
8687 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)
8688 {
8689         rsurface.entity = r_refdef.scene.worldentity;
8690         rsurface.skeleton = NULL;
8691         rsurface.ent_skinnum = 0;
8692         rsurface.ent_qwskin = -1;
8693         rsurface.ent_flags = entflags;
8694         rsurface.shadertime = r_refdef.scene.time - shadertime;
8695         rsurface.modelnumvertices = numvertices;
8696         rsurface.modelnumtriangles = numtriangles;
8697         rsurface.matrix = *matrix;
8698         rsurface.inversematrix = *inversematrix;
8699         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8700         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8701         R_EntityMatrix(&rsurface.matrix);
8702         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8703         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8704         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8705         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8706         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8707         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8708         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8709         rsurface.frameblend[0].lerp = 1;
8710         rsurface.ent_alttextures = false;
8711         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8712         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8713         rsurface.entityskeletaltransform3x4 = NULL;
8714         rsurface.entityskeletaltransform3x4buffer = NULL;
8715         rsurface.entityskeletaltransform3x4offset = 0;
8716         rsurface.entityskeletaltransform3x4size = 0;
8717         rsurface.entityskeletalnumtransforms = 0;
8718         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8719         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8720         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8721         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8722         if (wanttangents)
8723         {
8724                 rsurface.modelvertex3f = (float *)vertex3f;
8725                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8726                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8727                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8728         }
8729         else if (wantnormals)
8730         {
8731                 rsurface.modelvertex3f = (float *)vertex3f;
8732                 rsurface.modelsvector3f = NULL;
8733                 rsurface.modeltvector3f = NULL;
8734                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8735         }
8736         else
8737         {
8738                 rsurface.modelvertex3f = (float *)vertex3f;
8739                 rsurface.modelsvector3f = NULL;
8740                 rsurface.modeltvector3f = NULL;
8741                 rsurface.modelnormal3f = NULL;
8742         }
8743         rsurface.modelvertexmesh = NULL;
8744         rsurface.modelvertexmesh_vertexbuffer = NULL;
8745         rsurface.modelvertexmesh_bufferoffset = 0;
8746         rsurface.modelvertex3f_vertexbuffer = 0;
8747         rsurface.modelvertex3f_bufferoffset = 0;
8748         rsurface.modelsvector3f_vertexbuffer = 0;
8749         rsurface.modelsvector3f_bufferoffset = 0;
8750         rsurface.modeltvector3f_vertexbuffer = 0;
8751         rsurface.modeltvector3f_bufferoffset = 0;
8752         rsurface.modelnormal3f_vertexbuffer = 0;
8753         rsurface.modelnormal3f_bufferoffset = 0;
8754         rsurface.modelgeneratedvertex = true;
8755         rsurface.modellightmapcolor4f  = (float *)color4f;
8756         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8757         rsurface.modellightmapcolor4f_bufferoffset = 0;
8758         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8759         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8760         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8761         rsurface.modeltexcoordlightmap2f  = NULL;
8762         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8763         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8764         rsurface.modelskeletalindex4ub = NULL;
8765         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8766         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8767         rsurface.modelskeletalweight4ub = NULL;
8768         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8769         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8770         rsurface.modelelement3i = (int *)element3i;
8771         rsurface.modelelement3i_indexbuffer = NULL;
8772         rsurface.modelelement3i_bufferoffset = 0;
8773         rsurface.modelelement3s = (unsigned short *)element3s;
8774         rsurface.modelelement3s_indexbuffer = NULL;
8775         rsurface.modelelement3s_bufferoffset = 0;
8776         rsurface.modellightmapoffsets = NULL;
8777         rsurface.modelsurfaces = NULL;
8778         rsurface.batchgeneratedvertex = false;
8779         rsurface.batchfirstvertex = 0;
8780         rsurface.batchnumvertices = 0;
8781         rsurface.batchfirsttriangle = 0;
8782         rsurface.batchnumtriangles = 0;
8783         rsurface.batchvertex3f  = NULL;
8784         rsurface.batchvertex3f_vertexbuffer = NULL;
8785         rsurface.batchvertex3f_bufferoffset = 0;
8786         rsurface.batchsvector3f = NULL;
8787         rsurface.batchsvector3f_vertexbuffer = NULL;
8788         rsurface.batchsvector3f_bufferoffset = 0;
8789         rsurface.batchtvector3f = NULL;
8790         rsurface.batchtvector3f_vertexbuffer = NULL;
8791         rsurface.batchtvector3f_bufferoffset = 0;
8792         rsurface.batchnormal3f  = NULL;
8793         rsurface.batchnormal3f_vertexbuffer = NULL;
8794         rsurface.batchnormal3f_bufferoffset = 0;
8795         rsurface.batchlightmapcolor4f = NULL;
8796         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8797         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8798         rsurface.batchtexcoordtexture2f = NULL;
8799         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8800         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8801         rsurface.batchtexcoordlightmap2f = NULL;
8802         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8803         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8804         rsurface.batchskeletalindex4ub = NULL;
8805         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8806         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8807         rsurface.batchskeletalweight4ub = NULL;
8808         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8809         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8810         rsurface.batchvertexmesh = NULL;
8811         rsurface.batchvertexmesh_vertexbuffer = NULL;
8812         rsurface.batchvertexmesh_bufferoffset = 0;
8813         rsurface.batchelement3i = NULL;
8814         rsurface.batchelement3i_indexbuffer = NULL;
8815         rsurface.batchelement3i_bufferoffset = 0;
8816         rsurface.batchelement3s = NULL;
8817         rsurface.batchelement3s_indexbuffer = NULL;
8818         rsurface.batchelement3s_bufferoffset = 0;
8819         rsurface.passcolor4f = NULL;
8820         rsurface.passcolor4f_vertexbuffer = NULL;
8821         rsurface.passcolor4f_bufferoffset = 0;
8822         rsurface.forcecurrenttextureupdate = true;
8823
8824         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8825         {
8826                 if ((wantnormals || wanttangents) && !normal3f)
8827                 {
8828                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8829                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8830                 }
8831                 if (wanttangents && !svector3f)
8832                 {
8833                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8834                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8835                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8836                 }
8837         }
8838 }
8839
8840 float RSurf_FogPoint(const float *v)
8841 {
8842         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8843         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8844         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8845         float FogHeightFade = r_refdef.fogheightfade;
8846         float fogfrac;
8847         unsigned int fogmasktableindex;
8848         if (r_refdef.fogplaneviewabove)
8849                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8850         else
8851                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8852         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8853         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8854 }
8855
8856 float RSurf_FogVertex(const float *v)
8857 {
8858         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8859         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8860         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8861         float FogHeightFade = rsurface.fogheightfade;
8862         float fogfrac;
8863         unsigned int fogmasktableindex;
8864         if (r_refdef.fogplaneviewabove)
8865                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8866         else
8867                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8868         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8869         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8870 }
8871
8872 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8873 {
8874         int i;
8875         for (i = 0;i < numelements;i++)
8876                 outelement3i[i] = inelement3i[i] + adjust;
8877 }
8878
8879 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8880 extern cvar_t gl_vbo;
8881 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8882 {
8883         int deformindex;
8884         int firsttriangle;
8885         int numtriangles;
8886         int firstvertex;
8887         int endvertex;
8888         int numvertices;
8889         int surfacefirsttriangle;
8890         int surfacenumtriangles;
8891         int surfacefirstvertex;
8892         int surfaceendvertex;
8893         int surfacenumvertices;
8894         int batchnumsurfaces = texturenumsurfaces;
8895         int batchnumvertices;
8896         int batchnumtriangles;
8897         int needsupdate;
8898         int i, j;
8899         qboolean gaps;
8900         qboolean dynamicvertex;
8901         float amplitude;
8902         float animpos;
8903         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8904         float waveparms[4];
8905         unsigned char *ub;
8906         q3shaderinfo_deform_t *deform;
8907         const msurface_t *surface, *firstsurface;
8908         r_vertexmesh_t *vertexmesh;
8909         if (!texturenumsurfaces)
8910                 return;
8911         // find vertex range of this surface batch
8912         gaps = false;
8913         firstsurface = texturesurfacelist[0];
8914         firsttriangle = firstsurface->num_firsttriangle;
8915         batchnumvertices = 0;
8916         batchnumtriangles = 0;
8917         firstvertex = endvertex = firstsurface->num_firstvertex;
8918         for (i = 0;i < texturenumsurfaces;i++)
8919         {
8920                 surface = texturesurfacelist[i];
8921                 if (surface != firstsurface + i)
8922                         gaps = true;
8923                 surfacefirstvertex = surface->num_firstvertex;
8924                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8925                 surfacenumvertices = surface->num_vertices;
8926                 surfacenumtriangles = surface->num_triangles;
8927                 if (firstvertex > surfacefirstvertex)
8928                         firstvertex = surfacefirstvertex;
8929                 if (endvertex < surfaceendvertex)
8930                         endvertex = surfaceendvertex;
8931                 batchnumvertices += surfacenumvertices;
8932                 batchnumtriangles += surfacenumtriangles;
8933         }
8934
8935         r_refdef.stats[r_stat_batch_batches]++;
8936         if (gaps)
8937                 r_refdef.stats[r_stat_batch_withgaps]++;
8938         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8939         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8940         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8941
8942         // we now know the vertex range used, and if there are any gaps in it
8943         rsurface.batchfirstvertex = firstvertex;
8944         rsurface.batchnumvertices = endvertex - firstvertex;
8945         rsurface.batchfirsttriangle = firsttriangle;
8946         rsurface.batchnumtriangles = batchnumtriangles;
8947
8948         // this variable holds flags for which properties have been updated that
8949         // may require regenerating vertexmesh array...
8950         needsupdate = 0;
8951
8952         // check if any dynamic vertex processing must occur
8953         dynamicvertex = false;
8954
8955         // a cvar to force the dynamic vertex path to be taken, for debugging
8956         if (r_batch_debugdynamicvertexpath.integer)
8957         {
8958                 if (!dynamicvertex)
8959                 {
8960                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8961                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8962                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8963                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8964                 }
8965                 dynamicvertex = true;
8966         }
8967
8968         // if there is a chance of animated vertex colors, it's a dynamic batch
8969         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8970         {
8971                 if (!dynamicvertex)
8972                 {
8973                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8974                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8975                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8976                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8977                 }
8978                 dynamicvertex = true;
8979                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8980         }
8981
8982         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8983         {
8984                 switch (deform->deform)
8985                 {
8986                 default:
8987                 case Q3DEFORM_PROJECTIONSHADOW:
8988                 case Q3DEFORM_TEXT0:
8989                 case Q3DEFORM_TEXT1:
8990                 case Q3DEFORM_TEXT2:
8991                 case Q3DEFORM_TEXT3:
8992                 case Q3DEFORM_TEXT4:
8993                 case Q3DEFORM_TEXT5:
8994                 case Q3DEFORM_TEXT6:
8995                 case Q3DEFORM_TEXT7:
8996                 case Q3DEFORM_NONE:
8997                         break;
8998                 case Q3DEFORM_AUTOSPRITE:
8999                         if (!dynamicvertex)
9000                         {
9001                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9002                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9003                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9004                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9005                         }
9006                         dynamicvertex = true;
9007                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9008                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9009                         break;
9010                 case Q3DEFORM_AUTOSPRITE2:
9011                         if (!dynamicvertex)
9012                         {
9013                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9014                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9015                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9016                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9017                         }
9018                         dynamicvertex = true;
9019                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9020                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9021                         break;
9022                 case Q3DEFORM_NORMAL:
9023                         if (!dynamicvertex)
9024                         {
9025                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9026                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9027                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9028                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9029                         }
9030                         dynamicvertex = true;
9031                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9032                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9033                         break;
9034                 case Q3DEFORM_WAVE:
9035                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9036                                 break; // if wavefunc is a nop, ignore this transform
9037                         if (!dynamicvertex)
9038                         {
9039                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9040                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9041                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9042                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9043                         }
9044                         dynamicvertex = true;
9045                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9046                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9047                         break;
9048                 case Q3DEFORM_BULGE:
9049                         if (!dynamicvertex)
9050                         {
9051                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9052                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9053                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9054                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9055                         }
9056                         dynamicvertex = true;
9057                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9058                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9059                         break;
9060                 case Q3DEFORM_MOVE:
9061                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9062                                 break; // if wavefunc is a nop, ignore this transform
9063                         if (!dynamicvertex)
9064                         {
9065                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9066                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9067                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9068                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9069                         }
9070                         dynamicvertex = true;
9071                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9072                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9073                         break;
9074                 }
9075         }
9076         if (rsurface.texture->materialshaderpass)
9077         {
9078                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9079                 {
9080                 default:
9081                 case Q3TCGEN_TEXTURE:
9082                         break;
9083                 case Q3TCGEN_LIGHTMAP:
9084                         if (!dynamicvertex)
9085                         {
9086                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9087                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9088                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9089                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9090                         }
9091                         dynamicvertex = true;
9092                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9093                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9094                         break;
9095                 case Q3TCGEN_VECTOR:
9096                         if (!dynamicvertex)
9097                         {
9098                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9099                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9100                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9101                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9102                         }
9103                         dynamicvertex = true;
9104                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9105                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9106                         break;
9107                 case Q3TCGEN_ENVIRONMENT:
9108                         if (!dynamicvertex)
9109                         {
9110                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9111                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9112                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9113                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9114                         }
9115                         dynamicvertex = true;
9116                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9117                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9118                         break;
9119                 }
9120                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9121                 {
9122                         if (!dynamicvertex)
9123                         {
9124                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9125                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9126                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9127                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9128                         }
9129                         dynamicvertex = true;
9130                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9131                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9132                 }
9133         }
9134
9135         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9136         {
9137                 if (!dynamicvertex)
9138                 {
9139                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9140                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9141                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9142                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9143                 }
9144                 dynamicvertex = true;
9145                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9146         }
9147
9148         // when the model data has no vertex buffer (dynamic mesh), we need to
9149         // eliminate gaps
9150         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9151                 batchneed |= BATCHNEED_NOGAPS;
9152
9153         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9154         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9155         // we ensure this by treating the vertex batch as dynamic...
9156         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9157         {
9158                 if (!dynamicvertex)
9159                 {
9160                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9161                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9162                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9163                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9164                 }
9165                 dynamicvertex = true;
9166         }
9167
9168         if (dynamicvertex)
9169         {
9170                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9171                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9172                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9173                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9174                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9175                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9176                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9177                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9178         }
9179
9180         // if needsupdate, we have to do a dynamic vertex batch for sure
9181         if (needsupdate & batchneed)
9182         {
9183                 if (!dynamicvertex)
9184                 {
9185                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9186                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9187                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9188                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9189                 }
9190                 dynamicvertex = true;
9191         }
9192
9193         // see if we need to build vertexmesh from arrays
9194         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9195         {
9196                 if (!dynamicvertex)
9197                 {
9198                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9199                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9200                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9201                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9202                 }
9203                 dynamicvertex = true;
9204         }
9205
9206         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9207         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9208                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9209
9210         rsurface.batchvertex3f = rsurface.modelvertex3f;
9211         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9212         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9213         rsurface.batchsvector3f = rsurface.modelsvector3f;
9214         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9215         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9216         rsurface.batchtvector3f = rsurface.modeltvector3f;
9217         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9218         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9219         rsurface.batchnormal3f = rsurface.modelnormal3f;
9220         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9221         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9222         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9223         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9224         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9225         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9226         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9227         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9228         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9229         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9230         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9231         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9232         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9233         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9234         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9235         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9236         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9237         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9238         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9239         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9240         rsurface.batchelement3i = rsurface.modelelement3i;
9241         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9242         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9243         rsurface.batchelement3s = rsurface.modelelement3s;
9244         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9245         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9246         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9247         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9248         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9249         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9250         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9251
9252         // if any dynamic vertex processing has to occur in software, we copy the
9253         // entire surface list together before processing to rebase the vertices
9254         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9255         //
9256         // if any gaps exist and we do not have a static vertex buffer, we have to
9257         // copy the surface list together to avoid wasting upload bandwidth on the
9258         // vertices in the gaps.
9259         //
9260         // if gaps exist and we have a static vertex buffer, we can choose whether
9261         // to combine the index buffer ranges into one dynamic index buffer or
9262         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9263         //
9264         // in many cases the batch is reduced to one draw call.
9265
9266         rsurface.batchmultidraw = false;
9267         rsurface.batchmultidrawnumsurfaces = 0;
9268         rsurface.batchmultidrawsurfacelist = NULL;
9269
9270         if (!dynamicvertex)
9271         {
9272                 // static vertex data, just set pointers...
9273                 rsurface.batchgeneratedvertex = false;
9274                 // if there are gaps, we want to build a combined index buffer,
9275                 // otherwise use the original static buffer with an appropriate offset
9276                 if (gaps)
9277                 {
9278                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9279                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9280                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9281                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9282                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9283                         {
9284                                 rsurface.batchmultidraw = true;
9285                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9286                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9287                                 return;
9288                         }
9289                         // build a new triangle elements array for this batch
9290                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9291                         rsurface.batchfirsttriangle = 0;
9292                         numtriangles = 0;
9293                         for (i = 0;i < texturenumsurfaces;i++)
9294                         {
9295                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9296                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9297                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9298                                 numtriangles += surfacenumtriangles;
9299                         }
9300                         rsurface.batchelement3i_indexbuffer = NULL;
9301                         rsurface.batchelement3i_bufferoffset = 0;
9302                         rsurface.batchelement3s = NULL;
9303                         rsurface.batchelement3s_indexbuffer = NULL;
9304                         rsurface.batchelement3s_bufferoffset = 0;
9305                         if (endvertex <= 65536)
9306                         {
9307                                 // make a 16bit (unsigned short) index array if possible
9308                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9309                                 for (i = 0;i < numtriangles*3;i++)
9310                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9311                         }
9312                         // upload buffer data for the copytriangles batch
9313                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9314                         {
9315                                 if (rsurface.batchelement3s)
9316                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9317                                 else if (rsurface.batchelement3i)
9318                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9319                         }
9320                 }
9321                 else
9322                 {
9323                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9324                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9325                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9326                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9327                 }
9328                 return;
9329         }
9330
9331         // something needs software processing, do it for real...
9332         // we only directly handle separate array data in this case and then
9333         // generate interleaved data if needed...
9334         rsurface.batchgeneratedvertex = true;
9335         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9336         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9337         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9338         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9339
9340         // now copy the vertex data into a combined array and make an index array
9341         // (this is what Quake3 does all the time)
9342         // we also apply any skeletal animation here that would have been done in
9343         // the vertex shader, because most of the dynamic vertex animation cases
9344         // need actual vertex positions and normals
9345         //if (dynamicvertex)
9346         {
9347                 rsurface.batchvertexmesh = NULL;
9348                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9349                 rsurface.batchvertexmesh_bufferoffset = 0;
9350                 rsurface.batchvertex3f = NULL;
9351                 rsurface.batchvertex3f_vertexbuffer = NULL;
9352                 rsurface.batchvertex3f_bufferoffset = 0;
9353                 rsurface.batchsvector3f = NULL;
9354                 rsurface.batchsvector3f_vertexbuffer = NULL;
9355                 rsurface.batchsvector3f_bufferoffset = 0;
9356                 rsurface.batchtvector3f = NULL;
9357                 rsurface.batchtvector3f_vertexbuffer = NULL;
9358                 rsurface.batchtvector3f_bufferoffset = 0;
9359                 rsurface.batchnormal3f = NULL;
9360                 rsurface.batchnormal3f_vertexbuffer = NULL;
9361                 rsurface.batchnormal3f_bufferoffset = 0;
9362                 rsurface.batchlightmapcolor4f = NULL;
9363                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9364                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9365                 rsurface.batchtexcoordtexture2f = NULL;
9366                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9367                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9368                 rsurface.batchtexcoordlightmap2f = NULL;
9369                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9370                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9371                 rsurface.batchskeletalindex4ub = NULL;
9372                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9373                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9374                 rsurface.batchskeletalweight4ub = NULL;
9375                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9376                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9377                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9378                 rsurface.batchelement3i_indexbuffer = NULL;
9379                 rsurface.batchelement3i_bufferoffset = 0;
9380                 rsurface.batchelement3s = NULL;
9381                 rsurface.batchelement3s_indexbuffer = NULL;
9382                 rsurface.batchelement3s_bufferoffset = 0;
9383                 rsurface.batchskeletaltransform3x4buffer = NULL;
9384                 rsurface.batchskeletaltransform3x4offset = 0;
9385                 rsurface.batchskeletaltransform3x4size = 0;
9386                 // we'll only be setting up certain arrays as needed
9387                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9388                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9389                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9390                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9391                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9392                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9393                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9394                 {
9395                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9396                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9397                 }
9398                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9399                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9400                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9401                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9402                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9403                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9404                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9405                 {
9406                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9407                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9408                 }
9409                 numvertices = 0;
9410                 numtriangles = 0;
9411                 for (i = 0;i < texturenumsurfaces;i++)
9412                 {
9413                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9414                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9415                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9416                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9417                         // copy only the data requested
9418                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9419                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9420                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9421                         {
9422                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9423                                 {
9424                                         if (rsurface.batchvertex3f)
9425                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9426                                         else
9427                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9428                                 }
9429                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9430                                 {
9431                                         if (rsurface.modelnormal3f)
9432                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9433                                         else
9434                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9435                                 }
9436                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9437                                 {
9438                                         if (rsurface.modelsvector3f)
9439                                         {
9440                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9441                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9442                                         }
9443                                         else
9444                                         {
9445                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9446                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9447                                         }
9448                                 }
9449                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9450                                 {
9451                                         if (rsurface.modellightmapcolor4f)
9452                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9453                                         else
9454                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9455                                 }
9456                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9457                                 {
9458                                         if (rsurface.modeltexcoordtexture2f)
9459                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9460                                         else
9461                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9462                                 }
9463                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9464                                 {
9465                                         if (rsurface.modeltexcoordlightmap2f)
9466                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9467                                         else
9468                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9469                                 }
9470                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9471                                 {
9472                                         if (rsurface.modelskeletalindex4ub)
9473                                         {
9474                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9475                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9476                                         }
9477                                         else
9478                                         {
9479                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9480                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9481                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9482                                                 for (j = 0;j < surfacenumvertices;j++)
9483                                                         ub[j*4] = 255;
9484                                         }
9485                                 }
9486                         }
9487                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9488                         numvertices += surfacenumvertices;
9489                         numtriangles += surfacenumtriangles;
9490                 }
9491
9492                 // generate a 16bit index array as well if possible
9493                 // (in general, dynamic batches fit)
9494                 if (numvertices <= 65536)
9495                 {
9496                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9497                         for (i = 0;i < numtriangles*3;i++)
9498                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9499                 }
9500
9501                 // since we've copied everything, the batch now starts at 0
9502                 rsurface.batchfirstvertex = 0;
9503                 rsurface.batchnumvertices = batchnumvertices;
9504                 rsurface.batchfirsttriangle = 0;
9505                 rsurface.batchnumtriangles = batchnumtriangles;
9506         }
9507
9508         // apply skeletal animation that would have been done in the vertex shader
9509         if (rsurface.batchskeletaltransform3x4)
9510         {
9511                 const unsigned char *si;
9512                 const unsigned char *sw;
9513                 const float *t[4];
9514                 const float *b = rsurface.batchskeletaltransform3x4;
9515                 float *vp, *vs, *vt, *vn;
9516                 float w[4];
9517                 float m[3][4], n[3][4];
9518                 float tp[3], ts[3], tt[3], tn[3];
9519                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9520                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9521                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9522                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9523                 si = rsurface.batchskeletalindex4ub;
9524                 sw = rsurface.batchskeletalweight4ub;
9525                 vp = rsurface.batchvertex3f;
9526                 vs = rsurface.batchsvector3f;
9527                 vt = rsurface.batchtvector3f;
9528                 vn = rsurface.batchnormal3f;
9529                 memset(m[0], 0, sizeof(m));
9530                 memset(n[0], 0, sizeof(n));
9531                 for (i = 0;i < batchnumvertices;i++)
9532                 {
9533                         t[0] = b + si[0]*12;
9534                         if (sw[0] == 255)
9535                         {
9536                                 // common case - only one matrix
9537                                 m[0][0] = t[0][ 0];
9538                                 m[0][1] = t[0][ 1];
9539                                 m[0][2] = t[0][ 2];
9540                                 m[0][3] = t[0][ 3];
9541                                 m[1][0] = t[0][ 4];
9542                                 m[1][1] = t[0][ 5];
9543                                 m[1][2] = t[0][ 6];
9544                                 m[1][3] = t[0][ 7];
9545                                 m[2][0] = t[0][ 8];
9546                                 m[2][1] = t[0][ 9];
9547                                 m[2][2] = t[0][10];
9548                                 m[2][3] = t[0][11];
9549                         }
9550                         else if (sw[2] + sw[3])
9551                         {
9552                                 // blend 4 matrices
9553                                 t[1] = b + si[1]*12;
9554                                 t[2] = b + si[2]*12;
9555                                 t[3] = b + si[3]*12;
9556                                 w[0] = sw[0] * (1.0f / 255.0f);
9557                                 w[1] = sw[1] * (1.0f / 255.0f);
9558                                 w[2] = sw[2] * (1.0f / 255.0f);
9559                                 w[3] = sw[3] * (1.0f / 255.0f);
9560                                 // blend the matrices
9561                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9562                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9563                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9564                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9565                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9566                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9567                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9568                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9569                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9570                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9571                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9572                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9573                         }
9574                         else
9575                         {
9576                                 // blend 2 matrices
9577                                 t[1] = b + si[1]*12;
9578                                 w[0] = sw[0] * (1.0f / 255.0f);
9579                                 w[1] = sw[1] * (1.0f / 255.0f);
9580                                 // blend the matrices
9581                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9582                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9583                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9584                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9585                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9586                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9587                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9588                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9589                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9590                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9591                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9592                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9593                         }
9594                         si += 4;
9595                         sw += 4;
9596                         // modify the vertex
9597                         VectorCopy(vp, tp);
9598                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9599                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9600                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9601                         vp += 3;
9602                         if (vn)
9603                         {
9604                                 // the normal transformation matrix is a set of cross products...
9605                                 CrossProduct(m[1], m[2], n[0]);
9606                                 CrossProduct(m[2], m[0], n[1]);
9607                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9608                                 VectorCopy(vn, tn);
9609                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9610                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9611                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9612                                 VectorNormalize(vn);
9613                                 vn += 3;
9614                                 if (vs)
9615                                 {
9616                                         VectorCopy(vs, ts);
9617                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9618                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9619                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9620                                         VectorNormalize(vs);
9621                                         vs += 3;
9622                                         VectorCopy(vt, tt);
9623                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9624                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9625                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9626                                         VectorNormalize(vt);
9627                                         vt += 3;
9628                                 }
9629                         }
9630                 }
9631                 rsurface.batchskeletaltransform3x4 = NULL;
9632                 rsurface.batchskeletalnumtransforms = 0;
9633         }
9634
9635         // q1bsp surfaces rendered in vertex color mode have to have colors
9636         // calculated based on lightstyles
9637         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9638         {
9639                 // generate color arrays for the surfaces in this list
9640                 int c[4];
9641                 int scale;
9642                 int size3;
9643                 const int *offsets;
9644                 const unsigned char *lm;
9645                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9646                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9647                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9648                 numvertices = 0;
9649                 for (i = 0;i < texturenumsurfaces;i++)
9650                 {
9651                         surface = texturesurfacelist[i];
9652                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9653                         surfacenumvertices = surface->num_vertices;
9654                         if (surface->lightmapinfo->samples)
9655                         {
9656                                 for (j = 0;j < surfacenumvertices;j++)
9657                                 {
9658                                         lm = surface->lightmapinfo->samples + offsets[j];
9659                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9660                                         VectorScale(lm, scale, c);
9661                                         if (surface->lightmapinfo->styles[1] != 255)
9662                                         {
9663                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9664                                                 lm += size3;
9665                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9666                                                 VectorMA(c, scale, lm, c);
9667                                                 if (surface->lightmapinfo->styles[2] != 255)
9668                                                 {
9669                                                         lm += size3;
9670                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9671                                                         VectorMA(c, scale, lm, c);
9672                                                         if (surface->lightmapinfo->styles[3] != 255)
9673                                                         {
9674                                                                 lm += size3;
9675                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9676                                                                 VectorMA(c, scale, lm, c);
9677                                                         }
9678                                                 }
9679                                         }
9680                                         c[0] >>= 7;
9681                                         c[1] >>= 7;
9682                                         c[2] >>= 7;
9683                                         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);
9684                                         numvertices++;
9685                                 }
9686                         }
9687                         else
9688                         {
9689                                 for (j = 0;j < surfacenumvertices;j++)
9690                                 {
9691                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9692                                         numvertices++;
9693                                 }
9694                         }
9695                 }
9696         }
9697
9698         // if vertices are deformed (sprite flares and things in maps, possibly
9699         // water waves, bulges and other deformations), modify the copied vertices
9700         // in place
9701         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9702         {
9703                 float scale;
9704                 switch (deform->deform)
9705                 {
9706                 default:
9707                 case Q3DEFORM_PROJECTIONSHADOW:
9708                 case Q3DEFORM_TEXT0:
9709                 case Q3DEFORM_TEXT1:
9710                 case Q3DEFORM_TEXT2:
9711                 case Q3DEFORM_TEXT3:
9712                 case Q3DEFORM_TEXT4:
9713                 case Q3DEFORM_TEXT5:
9714                 case Q3DEFORM_TEXT6:
9715                 case Q3DEFORM_TEXT7:
9716                 case Q3DEFORM_NONE:
9717                         break;
9718                 case Q3DEFORM_AUTOSPRITE:
9719                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9720                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9721                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9722                         VectorNormalize(newforward);
9723                         VectorNormalize(newright);
9724                         VectorNormalize(newup);
9725 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9726 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9727 //                      rsurface.batchvertex3f_bufferoffset = 0;
9728 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9729 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9730 //                      rsurface.batchsvector3f_bufferoffset = 0;
9731 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9732 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9733 //                      rsurface.batchtvector3f_bufferoffset = 0;
9734 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9735 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9736 //                      rsurface.batchnormal3f_bufferoffset = 0;
9737                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9738                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9739                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9740                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9741                                 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);
9742                         // a single autosprite surface can contain multiple sprites...
9743                         for (j = 0;j < batchnumvertices - 3;j += 4)
9744                         {
9745                                 VectorClear(center);
9746                                 for (i = 0;i < 4;i++)
9747                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9748                                 VectorScale(center, 0.25f, center);
9749                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9750                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9751                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9752                                 for (i = 0;i < 4;i++)
9753                                 {
9754                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9755                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9756                                 }
9757                         }
9758                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9759                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9760                         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);
9761                         break;
9762                 case Q3DEFORM_AUTOSPRITE2:
9763                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9764                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9765                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9766                         VectorNormalize(newforward);
9767                         VectorNormalize(newright);
9768                         VectorNormalize(newup);
9769 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9770 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9771 //                      rsurface.batchvertex3f_bufferoffset = 0;
9772                         {
9773                                 const float *v1, *v2;
9774                                 vec3_t start, end;
9775                                 float f, l;
9776                                 struct
9777                                 {
9778                                         float length2;
9779                                         const float *v1;
9780                                         const float *v2;
9781                                 }
9782                                 shortest[2];
9783                                 memset(shortest, 0, sizeof(shortest));
9784                                 // a single autosprite surface can contain multiple sprites...
9785                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9786                                 {
9787                                         VectorClear(center);
9788                                         for (i = 0;i < 4;i++)
9789                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9790                                         VectorScale(center, 0.25f, center);
9791                                         // find the two shortest edges, then use them to define the
9792                                         // axis vectors for rotating around the central axis
9793                                         for (i = 0;i < 6;i++)
9794                                         {
9795                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9796                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9797                                                 l = VectorDistance2(v1, v2);
9798                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9799                                                 if (v1[2] != v2[2])
9800                                                         l += (1.0f / 1024.0f);
9801                                                 if (shortest[0].length2 > l || i == 0)
9802                                                 {
9803                                                         shortest[1] = shortest[0];
9804                                                         shortest[0].length2 = l;
9805                                                         shortest[0].v1 = v1;
9806                                                         shortest[0].v2 = v2;
9807                                                 }
9808                                                 else if (shortest[1].length2 > l || i == 1)
9809                                                 {
9810                                                         shortest[1].length2 = l;
9811                                                         shortest[1].v1 = v1;
9812                                                         shortest[1].v2 = v2;
9813                                                 }
9814                                         }
9815                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9816                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9817                                         // this calculates the right vector from the shortest edge
9818                                         // and the up vector from the edge midpoints
9819                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9820                                         VectorNormalize(right);
9821                                         VectorSubtract(end, start, up);
9822                                         VectorNormalize(up);
9823                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9824                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9825                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9826                                         VectorNegate(forward, forward);
9827                                         VectorReflect(forward, 0, up, forward);
9828                                         VectorNormalize(forward);
9829                                         CrossProduct(up, forward, newright);
9830                                         VectorNormalize(newright);
9831                                         // rotate the quad around the up axis vector, this is made
9832                                         // especially easy by the fact we know the quad is flat,
9833                                         // so we only have to subtract the center position and
9834                                         // measure distance along the right vector, and then
9835                                         // multiply that by the newright vector and add back the
9836                                         // center position
9837                                         // we also need to subtract the old position to undo the
9838                                         // displacement from the center, which we do with a
9839                                         // DotProduct, the subtraction/addition of center is also
9840                                         // optimized into DotProducts here
9841                                         l = DotProduct(right, center);
9842                                         for (i = 0;i < 4;i++)
9843                                         {
9844                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9845                                                 f = DotProduct(right, v1) - l;
9846                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9847                                         }
9848                                 }
9849                         }
9850                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9851                         {
9852 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9853 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9854 //                              rsurface.batchnormal3f_bufferoffset = 0;
9855                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9856                         }
9857                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9858                         {
9859 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9860 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9861 //                              rsurface.batchsvector3f_bufferoffset = 0;
9862 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9863 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9864 //                              rsurface.batchtvector3f_bufferoffset = 0;
9865                                 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);
9866                         }
9867                         break;
9868                 case Q3DEFORM_NORMAL:
9869                         // deform the normals to make reflections wavey
9870                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9871                         rsurface.batchnormal3f_vertexbuffer = NULL;
9872                         rsurface.batchnormal3f_bufferoffset = 0;
9873                         for (j = 0;j < batchnumvertices;j++)
9874                         {
9875                                 float vertex[3];
9876                                 float *normal = rsurface.batchnormal3f + 3*j;
9877                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9878                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9879                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9880                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9881                                 VectorNormalize(normal);
9882                         }
9883                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9884                         {
9885 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9886 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9887 //                              rsurface.batchsvector3f_bufferoffset = 0;
9888 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9889 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9890 //                              rsurface.batchtvector3f_bufferoffset = 0;
9891                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9892                         }
9893                         break;
9894                 case Q3DEFORM_WAVE:
9895                         // deform vertex array to make wavey water and flags and such
9896                         waveparms[0] = deform->waveparms[0];
9897                         waveparms[1] = deform->waveparms[1];
9898                         waveparms[2] = deform->waveparms[2];
9899                         waveparms[3] = deform->waveparms[3];
9900                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9901                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9902                         // this is how a divisor of vertex influence on deformation
9903                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9904                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9905 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9906 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9907 //                      rsurface.batchvertex3f_bufferoffset = 0;
9908 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9909 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9910 //                      rsurface.batchnormal3f_bufferoffset = 0;
9911                         for (j = 0;j < batchnumvertices;j++)
9912                         {
9913                                 // if the wavefunc depends on time, evaluate it per-vertex
9914                                 if (waveparms[3])
9915                                 {
9916                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9917                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9918                                 }
9919                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9920                         }
9921                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9922                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9923                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9924                         {
9925 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9926 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9927 //                              rsurface.batchsvector3f_bufferoffset = 0;
9928 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9929 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9930 //                              rsurface.batchtvector3f_bufferoffset = 0;
9931                                 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);
9932                         }
9933                         break;
9934                 case Q3DEFORM_BULGE:
9935                         // deform vertex array to make the surface have moving bulges
9936 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9937 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9938 //                      rsurface.batchvertex3f_bufferoffset = 0;
9939 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9940 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9941 //                      rsurface.batchnormal3f_bufferoffset = 0;
9942                         for (j = 0;j < batchnumvertices;j++)
9943                         {
9944                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9945                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9946                         }
9947                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9948                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9949                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9950                         {
9951 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9952 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9953 //                              rsurface.batchsvector3f_bufferoffset = 0;
9954 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9955 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9956 //                              rsurface.batchtvector3f_bufferoffset = 0;
9957                                 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);
9958                         }
9959                         break;
9960                 case Q3DEFORM_MOVE:
9961                         // deform vertex array
9962                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9963                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9964                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9965                         VectorScale(deform->parms, scale, waveparms);
9966 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9967 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9968 //                      rsurface.batchvertex3f_bufferoffset = 0;
9969                         for (j = 0;j < batchnumvertices;j++)
9970                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9971                         break;
9972                 }
9973         }
9974
9975         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
9976         {
9977         // generate texcoords based on the chosen texcoord source
9978                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
9979                 {
9980                 default:
9981                 case Q3TCGEN_TEXTURE:
9982                         break;
9983                 case Q3TCGEN_LIGHTMAP:
9984         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9985         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9986         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9987                         if (rsurface.batchtexcoordlightmap2f)
9988                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
9989                         break;
9990                 case Q3TCGEN_VECTOR:
9991         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9992         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9993         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9994                         for (j = 0;j < batchnumvertices;j++)
9995                         {
9996                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
9997                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
9998                         }
9999                         break;
10000                 case Q3TCGEN_ENVIRONMENT:
10001                         // make environment reflections using a spheremap
10002                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10003                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10004                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10005                         for (j = 0;j < batchnumvertices;j++)
10006                         {
10007                                 // identical to Q3A's method, but executed in worldspace so
10008                                 // carried models can be shiny too
10009
10010                                 float viewer[3], d, reflected[3], worldreflected[3];
10011
10012                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10013                                 // VectorNormalize(viewer);
10014
10015                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10016
10017                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10018                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10019                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10020                                 // note: this is proportinal to viewer, so we can normalize later
10021
10022                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10023                                 VectorNormalize(worldreflected);
10024
10025                                 // note: this sphere map only uses world x and z!
10026                                 // so positive and negative y will LOOK THE SAME.
10027                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10028                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10029                         }
10030                         break;
10031                 }
10032                 // the only tcmod that needs software vertex processing is turbulent, so
10033                 // check for it here and apply the changes if needed
10034                 // and we only support that as the first one
10035                 // (handling a mixture of turbulent and other tcmods would be problematic
10036                 //  without punting it entirely to a software path)
10037                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10038                 {
10039                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10040                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10041         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10042         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10043         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10044                         for (j = 0;j < batchnumvertices;j++)
10045                         {
10046                                 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);
10047                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10048                         }
10049                 }
10050         }
10051
10052         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10053         {
10054                 // convert the modified arrays to vertex structs
10055 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10056 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10057 //              rsurface.batchvertexmesh_bufferoffset = 0;
10058                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10059                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10060                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10061                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10062                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10063                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10064                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10065                 {
10066                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10067                         {
10068                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10069                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10070                         }
10071                 }
10072                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10073                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10074                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10075                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10076                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10077                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10078                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10079                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10080                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10081                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10082                 {
10083                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10084                         {
10085                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10086                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10087                         }
10088                 }
10089         }
10090
10091         // upload buffer data for the dynamic batch
10092         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10093         {
10094                 if (rsurface.batchvertexmesh)
10095                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10096                 else
10097                 {
10098                         if (rsurface.batchvertex3f)
10099                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10100                         if (rsurface.batchsvector3f)
10101                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10102                         if (rsurface.batchtvector3f)
10103                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10104                         if (rsurface.batchnormal3f)
10105                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10106                         if (rsurface.batchlightmapcolor4f)
10107                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10108                         if (rsurface.batchtexcoordtexture2f)
10109                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10110                         if (rsurface.batchtexcoordlightmap2f)
10111                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10112                         if (rsurface.batchskeletalindex4ub)
10113                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10114                         if (rsurface.batchskeletalweight4ub)
10115                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10116                 }
10117                 if (rsurface.batchelement3s)
10118                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10119                 else if (rsurface.batchelement3i)
10120                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10121         }
10122 }
10123
10124 void RSurf_DrawBatch(void)
10125 {
10126         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10127         // through the pipeline, killing it earlier in the pipeline would have
10128         // per-surface overhead rather than per-batch overhead, so it's best to
10129         // reject it here, before it hits glDraw.
10130         if (rsurface.batchnumtriangles == 0)
10131                 return;
10132 #if 0
10133         // batch debugging code
10134         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10135         {
10136                 int i;
10137                 int j;
10138                 int c;
10139                 const int *e;
10140                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10141                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10142                 {
10143                         c = e[i];
10144                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10145                         {
10146                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10147                                 {
10148                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10149                                                 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);
10150                                         break;
10151                                 }
10152                         }
10153                 }
10154         }
10155 #endif
10156         if (rsurface.batchmultidraw)
10157         {
10158                 // issue multiple draws rather than copying index data
10159                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10160                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10161                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10162                 for (i = 0;i < numsurfaces;)
10163                 {
10164                         // combine consecutive surfaces as one draw
10165                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10166                                 if (surfacelist[j] != surfacelist[k] + 1)
10167                                         break;
10168                         firstvertex = surfacelist[i]->num_firstvertex;
10169                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10170                         firsttriangle = surfacelist[i]->num_firsttriangle;
10171                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10172                         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);
10173                         i = j;
10174                 }
10175         }
10176         else
10177         {
10178                 // there is only one consecutive run of index data (may have been combined)
10179                 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);
10180         }
10181 }
10182
10183 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10184 {
10185         // pick the closest matching water plane
10186         int planeindex, vertexindex, bestplaneindex = -1;
10187         float d, bestd;
10188         vec3_t vert;
10189         const float *v;
10190         r_waterstate_waterplane_t *p;
10191         qboolean prepared = false;
10192         bestd = 0;
10193         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10194         {
10195                 if(p->camera_entity != rsurface.texture->camera_entity)
10196                         continue;
10197                 d = 0;
10198                 if(!prepared)
10199                 {
10200                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10201                         prepared = true;
10202                         if(rsurface.batchnumvertices == 0)
10203                                 break;
10204                 }
10205                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10206                 {
10207                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10208                         d += fabs(PlaneDiff(vert, &p->plane));
10209                 }
10210                 if (bestd > d || bestplaneindex < 0)
10211                 {
10212                         bestd = d;
10213                         bestplaneindex = planeindex;
10214                 }
10215         }
10216         return bestplaneindex;
10217         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10218         // this situation though, as it might be better to render single larger
10219         // batches with useless stuff (backface culled for example) than to
10220         // render multiple smaller batches
10221 }
10222
10223 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10224 {
10225         int i;
10226         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10227         rsurface.passcolor4f_vertexbuffer = 0;
10228         rsurface.passcolor4f_bufferoffset = 0;
10229         for (i = 0;i < rsurface.batchnumvertices;i++)
10230                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10231 }
10232
10233 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10234 {
10235         int i;
10236         float f;
10237         const float *v;
10238         const float *c;
10239         float *c2;
10240         if (rsurface.passcolor4f)
10241         {
10242                 // generate color arrays
10243                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10244                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10245                 rsurface.passcolor4f_vertexbuffer = 0;
10246                 rsurface.passcolor4f_bufferoffset = 0;
10247                 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)
10248                 {
10249                         f = RSurf_FogVertex(v);
10250                         c2[0] = c[0] * f;
10251                         c2[1] = c[1] * f;
10252                         c2[2] = c[2] * f;
10253                         c2[3] = c[3];
10254                 }
10255         }
10256         else
10257         {
10258                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10259                 rsurface.passcolor4f_vertexbuffer = 0;
10260                 rsurface.passcolor4f_bufferoffset = 0;
10261                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10262                 {
10263                         f = RSurf_FogVertex(v);
10264                         c2[0] = f;
10265                         c2[1] = f;
10266                         c2[2] = f;
10267                         c2[3] = 1;
10268                 }
10269         }
10270 }
10271
10272 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10273 {
10274         int i;
10275         float f;
10276         const float *v;
10277         const float *c;
10278         float *c2;
10279         if (!rsurface.passcolor4f)
10280                 return;
10281         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10282         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10283         rsurface.passcolor4f_vertexbuffer = 0;
10284         rsurface.passcolor4f_bufferoffset = 0;
10285         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)
10286         {
10287                 f = RSurf_FogVertex(v);
10288                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10289                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10290                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10291                 c2[3] = c[3];
10292         }
10293 }
10294
10295 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10296 {
10297         int i;
10298         const float *c;
10299         float *c2;
10300         if (!rsurface.passcolor4f)
10301                 return;
10302         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10303         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10304         rsurface.passcolor4f_vertexbuffer = 0;
10305         rsurface.passcolor4f_bufferoffset = 0;
10306         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10307         {
10308                 c2[0] = c[0] * r;
10309                 c2[1] = c[1] * g;
10310                 c2[2] = c[2] * b;
10311                 c2[3] = c[3] * a;
10312         }
10313 }
10314
10315 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10316 {
10317         int i;
10318         const float *c;
10319         float *c2;
10320         if (!rsurface.passcolor4f)
10321                 return;
10322         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10323         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10324         rsurface.passcolor4f_vertexbuffer = 0;
10325         rsurface.passcolor4f_bufferoffset = 0;
10326         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10327         {
10328                 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10329                 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10330                 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10331                 c2[3] = c[3];
10332         }
10333 }
10334
10335 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10336 {
10337         // TODO: optimize
10338         rsurface.passcolor4f = NULL;
10339         rsurface.passcolor4f_vertexbuffer = 0;
10340         rsurface.passcolor4f_bufferoffset = 0;
10341         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10342         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10343         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10344         GL_Color(r, g, b, a);
10345         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10346         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10347         R_Mesh_TexMatrix(0, NULL);
10348         RSurf_DrawBatch();
10349 }
10350
10351 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10352 {
10353         // TODO: optimize applyfog && applycolor case
10354         // just apply fog if necessary, and tint the fog color array if necessary
10355         rsurface.passcolor4f = NULL;
10356         rsurface.passcolor4f_vertexbuffer = 0;
10357         rsurface.passcolor4f_bufferoffset = 0;
10358         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10359         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10360         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10361         GL_Color(r, g, b, a);
10362         RSurf_DrawBatch();
10363 }
10364
10365 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10366 {
10367         // TODO: optimize
10368         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10369         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10370         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10371         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10372         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10373         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10374         GL_Color(r, g, b, a);
10375         RSurf_DrawBatch();
10376 }
10377
10378 static void RSurf_DrawBatch_GL11_ClampColor(void)
10379 {
10380         int i;
10381         const float *c1;
10382         float *c2;
10383         if (!rsurface.passcolor4f)
10384                 return;
10385         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10386         {
10387                 c2[0] = bound(0.0f, c1[0], 1.0f);
10388                 c2[1] = bound(0.0f, c1[1], 1.0f);
10389                 c2[2] = bound(0.0f, c1[2], 1.0f);
10390                 c2[3] = bound(0.0f, c1[3], 1.0f);
10391         }
10392 }
10393
10394 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10395 {
10396         int i;
10397         float f;
10398         const float *v;
10399         const float *n;
10400         float *c;
10401         //vec3_t eyedir;
10402
10403         // fake shading
10404         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10405         rsurface.passcolor4f_vertexbuffer = 0;
10406         rsurface.passcolor4f_bufferoffset = 0;
10407         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)
10408         {
10409                 f = -DotProduct(r_refdef.view.forward, n);
10410                 f = max(0, f);
10411                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10412                 f *= fakelightintensity;
10413                 Vector4Set(c, f, f, f, 1);
10414         }
10415 }
10416
10417 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10418 {
10419         RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10420         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10421         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10422         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10423         GL_Color(r, g, b, a);
10424         RSurf_DrawBatch();
10425 }
10426
10427 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10428 {
10429         int i;
10430         float f;
10431         float alpha;
10432         const float *v;
10433         const float *n;
10434         float *c;
10435         vec3_t ambientcolor;
10436         vec3_t diffusecolor;
10437         vec3_t lightdir;
10438         // TODO: optimize
10439         // model lighting
10440         VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10441         f = 0.5f * lightmapintensity;
10442         ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10443         ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10444         ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10445         diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10446         diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10447         diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10448         alpha = *a;
10449         if (VectorLength2(diffusecolor) > 0)
10450         {
10451                 // q3-style directional shading
10452                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10453                 rsurface.passcolor4f_vertexbuffer = 0;
10454                 rsurface.passcolor4f_bufferoffset = 0;
10455                 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)
10456                 {
10457                         if ((f = DotProduct(n, lightdir)) > 0)
10458                                 VectorMA(ambientcolor, f, diffusecolor, c);
10459                         else
10460                                 VectorCopy(ambientcolor, c);
10461                         c[3] = alpha;
10462                 }
10463                 *r = 1;
10464                 *g = 1;
10465                 *b = 1;
10466                 *a = 1;
10467                 *applycolor = false;
10468         }
10469         else
10470         {
10471                 *r = ambientcolor[0];
10472                 *g = ambientcolor[1];
10473                 *b = ambientcolor[2];
10474                 rsurface.passcolor4f = NULL;
10475                 rsurface.passcolor4f_vertexbuffer = 0;
10476                 rsurface.passcolor4f_bufferoffset = 0;
10477         }
10478 }
10479
10480 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10481 {
10482         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10483         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10484         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10485         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10486         GL_Color(r, g, b, a);
10487         RSurf_DrawBatch();
10488 }
10489
10490 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10491 {
10492         int i;
10493         float f;
10494         const float *v;
10495         float *c;
10496
10497         // fake shading
10498         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10499         rsurface.passcolor4f_vertexbuffer = 0;
10500         rsurface.passcolor4f_bufferoffset = 0;
10501
10502         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10503         {
10504                 f = 1 - RSurf_FogVertex(v);
10505                 c[0] = r;
10506                 c[1] = g;
10507                 c[2] = b;
10508                 c[3] = f * a;
10509         }
10510 }
10511
10512 void RSurf_SetupDepthAndCulling(void)
10513 {
10514         // submodels are biased to avoid z-fighting with world surfaces that they
10515         // may be exactly overlapping (avoids z-fighting artifacts on certain
10516         // doors and things in Quake maps)
10517         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10518         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10519         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10520         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10521 }
10522
10523 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10524 {
10525         // transparent sky would be ridiculous
10526         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10527                 return;
10528         R_SetupShader_Generic_NoTexture(false, false);
10529         skyrenderlater = true;
10530         RSurf_SetupDepthAndCulling();
10531         GL_DepthMask(true);
10532         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10533         // skymasking on them, and Quake3 never did sky masking (unlike
10534         // software Quake and software Quake2), so disable the sky masking
10535         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10536         // and skymasking also looks very bad when noclipping outside the
10537         // level, so don't use it then either.
10538         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10539         {
10540                 R_Mesh_ResetTextureState();
10541                 if (skyrendermasked)
10542                 {
10543                         R_SetupShader_DepthOrShadow(false, false, false);
10544                         // depth-only (masking)
10545                         GL_ColorMask(0,0,0,0);
10546                         // just to make sure that braindead drivers don't draw
10547                         // anything despite that colormask...
10548                         GL_BlendFunc(GL_ZERO, GL_ONE);
10549                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10550                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10551                 }
10552                 else
10553                 {
10554                         R_SetupShader_Generic_NoTexture(false, false);
10555                         // fog sky
10556                         GL_BlendFunc(GL_ONE, GL_ZERO);
10557                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10558                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10559                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10560                 }
10561                 RSurf_DrawBatch();
10562                 if (skyrendermasked)
10563                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10564         }
10565         R_Mesh_ResetTextureState();
10566         GL_Color(1, 1, 1, 1);
10567 }
10568
10569 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10570 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10571 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10572 {
10573         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10574                 return;
10575         if (prepass)
10576         {
10577                 // render screenspace normalmap to texture
10578                 GL_DepthMask(true);
10579                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10580                 RSurf_DrawBatch();
10581                 return;
10582         }
10583
10584         // bind lightmap texture
10585
10586         // water/refraction/reflection/camera surfaces have to be handled specially
10587         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10588         {
10589                 int start, end, startplaneindex;
10590                 for (start = 0;start < texturenumsurfaces;start = end)
10591                 {
10592                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10593                         if(startplaneindex < 0)
10594                         {
10595                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10596                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10597                                 end = start + 1;
10598                                 continue;
10599                         }
10600                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10601                                 ;
10602                         // now that we have a batch using the same planeindex, render it
10603                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10604                         {
10605                                 // render water or distortion background
10606                                 GL_DepthMask(true);
10607                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10608                                 RSurf_DrawBatch();
10609                                 // blend surface on top
10610                                 GL_DepthMask(false);
10611                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10612                                 RSurf_DrawBatch();
10613                         }
10614                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10615                         {
10616                                 // render surface with reflection texture as input
10617                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10618                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10619                                 RSurf_DrawBatch();
10620                         }
10621                 }
10622                 return;
10623         }
10624
10625         // render surface batch normally
10626         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10627         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10628         RSurf_DrawBatch();
10629 }
10630
10631 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10632 {
10633         // OpenGL 1.3 path - anything not completely ancient
10634         qboolean applycolor;
10635         qboolean applyfog;
10636         int layerindex;
10637         const texturelayer_t *layer;
10638         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10639         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10640
10641         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10642         {
10643                 vec4_t layercolor;
10644                 int layertexrgbscale;
10645                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10646                 {
10647                         if (layerindex == 0)
10648                                 GL_AlphaTest(true);
10649                         else
10650                         {
10651                                 GL_AlphaTest(false);
10652                                 GL_DepthFunc(GL_EQUAL);
10653                         }
10654                 }
10655                 GL_DepthMask(layer->depthmask && writedepth);
10656                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10657                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10658                 {
10659                         layertexrgbscale = 4;
10660                         VectorScale(layer->color, 0.25f, layercolor);
10661                 }
10662                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10663                 {
10664                         layertexrgbscale = 2;
10665                         VectorScale(layer->color, 0.5f, layercolor);
10666                 }
10667                 else
10668                 {
10669                         layertexrgbscale = 1;
10670                         VectorScale(layer->color, 1.0f, layercolor);
10671                 }
10672                 layercolor[3] = layer->color[3];
10673                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10674                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10675                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10676                 switch (layer->type)
10677                 {
10678                 case TEXTURELAYERTYPE_LITTEXTURE:
10679                         // single-pass lightmapped texture with 2x rgbscale
10680                         R_Mesh_TexBind(0, r_texture_white);
10681                         R_Mesh_TexMatrix(0, NULL);
10682                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10683                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10684                         R_Mesh_TexBind(1, layer->texture);
10685                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10686                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10687                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10688                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10689                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10690                         else if (FAKELIGHT_ENABLED)
10691                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10692                         else if (rsurface.uselightmaptexture)
10693                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10694                         else
10695                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10696                         break;
10697                 case TEXTURELAYERTYPE_TEXTURE:
10698                         // singletexture unlit texture with transparency support
10699                         R_Mesh_TexBind(0, layer->texture);
10700                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10701                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10702                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10703                         R_Mesh_TexBind(1, 0);
10704                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10705                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10706                         break;
10707                 case TEXTURELAYERTYPE_FOG:
10708                         // singletexture fogging
10709                         if (layer->texture)
10710                         {
10711                                 R_Mesh_TexBind(0, layer->texture);
10712                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10713                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10714                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10715                         }
10716                         else
10717                         {
10718                                 R_Mesh_TexBind(0, 0);
10719                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10720                         }
10721                         R_Mesh_TexBind(1, 0);
10722                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10723                         // generate a color array for the fog pass
10724                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10725                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10726                         RSurf_DrawBatch();
10727                         break;
10728                 default:
10729                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10730                 }
10731         }
10732         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10733         {
10734                 GL_DepthFunc(GL_LEQUAL);
10735                 GL_AlphaTest(false);
10736         }
10737 }
10738
10739 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10740 {
10741         // OpenGL 1.1 - crusty old voodoo path
10742         qboolean applyfog;
10743         int layerindex;
10744         const texturelayer_t *layer;
10745         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10746         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10747
10748         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10749         {
10750                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10751                 {
10752                         if (layerindex == 0)
10753                                 GL_AlphaTest(true);
10754                         else
10755                         {
10756                                 GL_AlphaTest(false);
10757                                 GL_DepthFunc(GL_EQUAL);
10758                         }
10759                 }
10760                 GL_DepthMask(layer->depthmask && writedepth);
10761                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10762                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10763                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10764                 switch (layer->type)
10765                 {
10766                 case TEXTURELAYERTYPE_LITTEXTURE:
10767                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10768                         {
10769                                 // two-pass lit texture with 2x rgbscale
10770                                 // first the lightmap pass
10771                                 R_Mesh_TexBind(0, r_texture_white);
10772                                 R_Mesh_TexMatrix(0, NULL);
10773                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10774                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10775                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10776                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10777                                 else if (FAKELIGHT_ENABLED)
10778                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10779                                 else if (rsurface.uselightmaptexture)
10780                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10781                                 else
10782                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10783                                 // then apply the texture to it
10784                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10785                                 R_Mesh_TexBind(0, layer->texture);
10786                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10787                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10788                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10789                                 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);
10790                         }
10791                         else
10792                         {
10793                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10794                                 R_Mesh_TexBind(0, layer->texture);
10795                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10796                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10797                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10798                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10799                                         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);
10800                                 else if (FAKELIGHT_ENABLED)
10801                                         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);
10802                                 else
10803                                         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);
10804                         }
10805                         break;
10806                 case TEXTURELAYERTYPE_TEXTURE:
10807                         // singletexture unlit texture with transparency support
10808                         R_Mesh_TexBind(0, layer->texture);
10809                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10810                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10811                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10812                         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);
10813                         break;
10814                 case TEXTURELAYERTYPE_FOG:
10815                         // singletexture fogging
10816                         if (layer->texture)
10817                         {
10818                                 R_Mesh_TexBind(0, layer->texture);
10819                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10820                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10821                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10822                         }
10823                         else
10824                         {
10825                                 R_Mesh_TexBind(0, 0);
10826                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10827                         }
10828                         // generate a color array for the fog pass
10829                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10830                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10831                         RSurf_DrawBatch();
10832                         break;
10833                 default:
10834                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10835                 }
10836         }
10837         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10838         {
10839                 GL_DepthFunc(GL_LEQUAL);
10840                 GL_AlphaTest(false);
10841         }
10842 }
10843
10844 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10845 {
10846         int vi;
10847         int j;
10848         r_vertexgeneric_t *batchvertex;
10849         float c[4];
10850         texture_t *t = rsurface.texture;
10851
10852 //      R_Mesh_ResetTextureState();
10853         R_SetupShader_Generic_NoTexture(false, false);
10854
10855         if(t && t->currentskinframe)
10856         {
10857                 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10858                 c[3] *= t->currentalpha;
10859         }
10860         else
10861         {
10862                 c[0] = 1;
10863                 c[1] = 0;
10864                 c[2] = 1;
10865                 c[3] = 1;
10866         }
10867
10868         if (t->pantstexture || t->shirttexture)
10869         {
10870                 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10871                 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10872                 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10873         }
10874
10875         // brighten it up (as texture value 127 means "unlit")
10876         c[0] *= 2 * r_refdef.view.colorscale;
10877         c[1] *= 2 * r_refdef.view.colorscale;
10878         c[2] *= 2 * r_refdef.view.colorscale;
10879
10880         if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10881                 c[3] *= r_wateralpha.value;
10882
10883         if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10884         {
10885                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10886                 GL_DepthMask(false);
10887         }
10888         else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10889         {
10890                 GL_BlendFunc(GL_ONE, GL_ONE);
10891                 GL_DepthMask(false);
10892         }
10893         else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10894         {
10895                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10896                 GL_DepthMask(false);
10897         }
10898         else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10899         {
10900                 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
10901                 GL_DepthMask(false);
10902         }
10903         else
10904         {
10905                 GL_BlendFunc(GL_ONE, GL_ZERO);
10906                 GL_DepthMask(writedepth);
10907         }
10908
10909         if (r_showsurfaces.integer == 3)
10910         {
10911                 rsurface.passcolor4f = NULL;
10912
10913                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10914                 {
10915                         qboolean applycolor = true;
10916                         float one = 1.0;
10917
10918                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10919
10920                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
10921                 }
10922                 else if (FAKELIGHT_ENABLED)
10923                 {
10924                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10925
10926                         RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
10927                 }
10928                 else
10929                 {
10930                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10931
10932                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10933                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10934                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10935                         RSurf_DrawBatch_GL11_ApplyAmbient();
10936                 }
10937
10938                 if(!rsurface.passcolor4f)
10939                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10940
10941                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10942                 if(r_refdef.fogenabled)
10943                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10944                 RSurf_DrawBatch_GL11_ClampColor();
10945
10946                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10947                 R_SetupShader_Generic_NoTexture(false, false);
10948                 RSurf_DrawBatch();
10949         }
10950         else if (!r_refdef.view.showdebug)
10951         {
10952                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10953                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10954                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10955                 {
10956                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10957                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10958                 }
10959                 R_Mesh_PrepareVertices_Generic_Unlock();
10960                 RSurf_DrawBatch();
10961         }
10962         else if (r_showsurfaces.integer == 4)
10963         {
10964                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10965                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10966                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10967                 {
10968                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
10969                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10970                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
10971                 }
10972                 R_Mesh_PrepareVertices_Generic_Unlock();
10973                 RSurf_DrawBatch();
10974         }
10975         else if (r_showsurfaces.integer == 2)
10976         {
10977                 const int *e;
10978                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10979                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10980                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10981                 {
10982                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10983                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10984                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10985                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10986                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
10987                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
10988                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
10989                 }
10990                 R_Mesh_PrepareVertices_Generic_Unlock();
10991                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10992         }
10993         else
10994         {
10995                 int texturesurfaceindex;
10996                 int k;
10997                 const msurface_t *surface;
10998                 float surfacecolor4f[4];
10999                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11000                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11001                 vi = 0;
11002                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11003                 {
11004                         surface = texturesurfacelist[texturesurfaceindex];
11005                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11006                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11007                         for (j = 0;j < surface->num_vertices;j++)
11008                         {
11009                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11010                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11011                                 vi++;
11012                         }
11013                 }
11014                 R_Mesh_PrepareVertices_Generic_Unlock();
11015                 RSurf_DrawBatch();
11016         }
11017 }
11018
11019 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11020 {
11021         CHECKGLERROR
11022         RSurf_SetupDepthAndCulling();
11023         if (r_showsurfaces.integer)
11024         {
11025                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11026                 return;
11027         }
11028         switch (vid.renderpath)
11029         {
11030         case RENDERPATH_GL20:
11031         case RENDERPATH_D3D9:
11032         case RENDERPATH_D3D10:
11033         case RENDERPATH_D3D11:
11034         case RENDERPATH_SOFT:
11035         case RENDERPATH_GLES2:
11036                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11037                 break;
11038         case RENDERPATH_GL13:
11039         case RENDERPATH_GLES1:
11040                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11041                 break;
11042         case RENDERPATH_GL11:
11043                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11044                 break;
11045         }
11046         CHECKGLERROR
11047 }
11048
11049 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11050 {
11051         int i, j;
11052         int texturenumsurfaces, endsurface;
11053         texture_t *texture;
11054         const msurface_t *surface;
11055         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11056
11057         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11058                 RSurf_ActiveModelEntity(ent, false, false, false);
11059         else
11060         {
11061                 switch (vid.renderpath)
11062                 {
11063                 case RENDERPATH_GL20:
11064                 case RENDERPATH_D3D9:
11065                 case RENDERPATH_D3D10:
11066                 case RENDERPATH_D3D11:
11067                 case RENDERPATH_SOFT:
11068                 case RENDERPATH_GLES2:
11069                         RSurf_ActiveModelEntity(ent, true, true, false);
11070                         break;
11071                 case RENDERPATH_GL11:
11072                 case RENDERPATH_GL13:
11073                 case RENDERPATH_GLES1:
11074                         RSurf_ActiveModelEntity(ent, true, false, false);
11075                         break;
11076                 }
11077         }
11078
11079         if (r_transparentdepthmasking.integer)
11080         {
11081                 qboolean setup = false;
11082                 for (i = 0;i < numsurfaces;i = j)
11083                 {
11084                         j = i + 1;
11085                         surface = rsurface.modelsurfaces + surfacelist[i];
11086                         texture = surface->texture;
11087                         rsurface.texture = R_GetCurrentTexture(texture);
11088                         rsurface.lightmaptexture = NULL;
11089                         rsurface.deluxemaptexture = NULL;
11090                         rsurface.uselightmaptexture = false;
11091                         // scan ahead until we find a different texture
11092                         endsurface = min(i + 1024, numsurfaces);
11093                         texturenumsurfaces = 0;
11094                         texturesurfacelist[texturenumsurfaces++] = surface;
11095                         for (;j < endsurface;j++)
11096                         {
11097                                 surface = rsurface.modelsurfaces + surfacelist[j];
11098                                 if (texture != surface->texture)
11099                                         break;
11100                                 texturesurfacelist[texturenumsurfaces++] = surface;
11101                         }
11102                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11103                                 continue;
11104                         // render the range of surfaces as depth
11105                         if (!setup)
11106                         {
11107                                 setup = true;
11108                                 GL_ColorMask(0,0,0,0);
11109                                 GL_Color(1,1,1,1);
11110                                 GL_DepthTest(true);
11111                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11112                                 GL_DepthMask(true);
11113 //                              R_Mesh_ResetTextureState();
11114                         }
11115                         RSurf_SetupDepthAndCulling();
11116                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11117                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11118                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11119                         RSurf_DrawBatch();
11120                 }
11121                 if (setup)
11122                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11123         }
11124
11125         for (i = 0;i < numsurfaces;i = j)
11126         {
11127                 j = i + 1;
11128                 surface = rsurface.modelsurfaces + surfacelist[i];
11129                 texture = surface->texture;
11130                 rsurface.texture = R_GetCurrentTexture(texture);
11131                 // scan ahead until we find a different texture
11132                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11133                 texturenumsurfaces = 0;
11134                 texturesurfacelist[texturenumsurfaces++] = surface;
11135                 if(FAKELIGHT_ENABLED)
11136                 {
11137                         rsurface.lightmaptexture = NULL;
11138                         rsurface.deluxemaptexture = NULL;
11139                         rsurface.uselightmaptexture = false;
11140                         for (;j < endsurface;j++)
11141                         {
11142                                 surface = rsurface.modelsurfaces + surfacelist[j];
11143                                 if (texture != surface->texture)
11144                                         break;
11145                                 texturesurfacelist[texturenumsurfaces++] = surface;
11146                         }
11147                 }
11148                 else
11149                 {
11150                         rsurface.lightmaptexture = surface->lightmaptexture;
11151                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11152                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11153                         for (;j < endsurface;j++)
11154                         {
11155                                 surface = rsurface.modelsurfaces + surfacelist[j];
11156                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11157                                         break;
11158                                 texturesurfacelist[texturenumsurfaces++] = surface;
11159                         }
11160                 }
11161                 // render the range of surfaces
11162                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11163         }
11164         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11165 }
11166
11167 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11168 {
11169         // transparent surfaces get pushed off into the transparent queue
11170         int surfacelistindex;
11171         const msurface_t *surface;
11172         vec3_t tempcenter, center;
11173         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11174         {
11175                 surface = texturesurfacelist[surfacelistindex];
11176                 if (r_transparent_sortsurfacesbynearest.integer)
11177                 {
11178                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11179                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11180                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11181                 }
11182                 else
11183                 {
11184                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11185                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11186                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11187                 }
11188                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11189                 if (rsurface.entity->transparent_offset) // transparent offset
11190                 {
11191                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11192                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11193                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11194                 }
11195                 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);
11196         }
11197 }
11198
11199 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11200 {
11201         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11202                 return;
11203         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11204                 return;
11205         RSurf_SetupDepthAndCulling();
11206         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11207         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11208         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11209         RSurf_DrawBatch();
11210 }
11211
11212 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11213 {
11214         CHECKGLERROR
11215         if (depthonly)
11216                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11217         else if (prepass)
11218         {
11219                 if (!rsurface.texture->currentnumlayers)
11220                         return;
11221                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11222                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11223                 else
11224                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11225         }
11226         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11227                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11228         else if (!rsurface.texture->currentnumlayers)
11229                 return;
11230         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11231         {
11232                 // in the deferred case, transparent surfaces were queued during prepass
11233                 if (!r_shadow_usingdeferredprepass)
11234                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11235         }
11236         else
11237         {
11238                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11239                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11240         }
11241         CHECKGLERROR
11242 }
11243
11244 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11245 {
11246         int i, j;
11247         texture_t *texture;
11248         R_FrameData_SetMark();
11249         // break the surface list down into batches by texture and use of lightmapping
11250         for (i = 0;i < numsurfaces;i = j)
11251         {
11252                 j = i + 1;
11253                 // texture is the base texture pointer, rsurface.texture is the
11254                 // current frame/skin the texture is directing us to use (for example
11255                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11256                 // use skin 1 instead)
11257                 texture = surfacelist[i]->texture;
11258                 rsurface.texture = R_GetCurrentTexture(texture);
11259                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11260                 {
11261                         // if this texture is not the kind we want, skip ahead to the next one
11262                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11263                                 ;
11264                         continue;
11265                 }
11266                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11267                 {
11268                         rsurface.lightmaptexture = NULL;
11269                         rsurface.deluxemaptexture = NULL;
11270                         rsurface.uselightmaptexture = false;
11271                         // simply scan ahead until we find a different texture or lightmap state
11272                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11273                                 ;
11274                 }
11275                 else
11276                 {
11277                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11278                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11279                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11280                         // simply scan ahead until we find a different texture or lightmap state
11281                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11282                                 ;
11283                 }
11284                 // render the range of surfaces
11285                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11286         }
11287         R_FrameData_ReturnToMark();
11288 }
11289
11290 float locboxvertex3f[6*4*3] =
11291 {
11292         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11293         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11294         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11295         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11296         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11297         1,0,0, 0,0,0, 0,1,0, 1,1,0
11298 };
11299
11300 unsigned short locboxelements[6*2*3] =
11301 {
11302          0, 1, 2, 0, 2, 3,
11303          4, 5, 6, 4, 6, 7,
11304          8, 9,10, 8,10,11,
11305         12,13,14, 12,14,15,
11306         16,17,18, 16,18,19,
11307         20,21,22, 20,22,23
11308 };
11309
11310 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11311 {
11312         int i, j;
11313         cl_locnode_t *loc = (cl_locnode_t *)ent;
11314         vec3_t mins, size;
11315         float vertex3f[6*4*3];
11316         CHECKGLERROR
11317         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11318         GL_DepthMask(false);
11319         GL_DepthRange(0, 1);
11320         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11321         GL_DepthTest(true);
11322         GL_CullFace(GL_NONE);
11323         R_EntityMatrix(&identitymatrix);
11324
11325 //      R_Mesh_ResetTextureState();
11326
11327         i = surfacelist[0];
11328         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11329                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11330                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11331                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11332
11333         if (VectorCompare(loc->mins, loc->maxs))
11334         {
11335                 VectorSet(size, 2, 2, 2);
11336                 VectorMA(loc->mins, -0.5f, size, mins);
11337         }
11338         else
11339         {
11340                 VectorCopy(loc->mins, mins);
11341                 VectorSubtract(loc->maxs, loc->mins, size);
11342         }
11343
11344         for (i = 0;i < 6*4*3;)
11345                 for (j = 0;j < 3;j++, i++)
11346                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11347
11348         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11349         R_SetupShader_Generic_NoTexture(false, false);
11350         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11351 }
11352
11353 void R_DrawLocs(void)
11354 {
11355         int index;
11356         cl_locnode_t *loc, *nearestloc;
11357         vec3_t center;
11358         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11359         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11360         {
11361                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11362                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11363         }
11364 }
11365
11366 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11367 {
11368         if (decalsystem->decals)
11369                 Mem_Free(decalsystem->decals);
11370         memset(decalsystem, 0, sizeof(*decalsystem));
11371 }
11372
11373 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)
11374 {
11375         tridecal_t *decal;
11376         tridecal_t *decals;
11377         int i;
11378
11379         // expand or initialize the system
11380         if (decalsystem->maxdecals <= decalsystem->numdecals)
11381         {
11382                 decalsystem_t old = *decalsystem;
11383                 qboolean useshortelements;
11384                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11385                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11386                 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)));
11387                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11388                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11389                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11390                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11391                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11392                 if (decalsystem->numdecals)
11393                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11394                 if (old.decals)
11395                         Mem_Free(old.decals);
11396                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11397                         decalsystem->element3i[i] = i;
11398                 if (useshortelements)
11399                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11400                                 decalsystem->element3s[i] = i;
11401         }
11402
11403         // grab a decal and search for another free slot for the next one
11404         decals = decalsystem->decals;
11405         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11406         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11407                 ;
11408         decalsystem->freedecal = i;
11409         if (decalsystem->numdecals <= i)
11410                 decalsystem->numdecals = i + 1;
11411
11412         // initialize the decal
11413         decal->lived = 0;
11414         decal->triangleindex = triangleindex;
11415         decal->surfaceindex = surfaceindex;
11416         decal->decalsequence = decalsequence;
11417         decal->color4f[0][0] = c0[0];
11418         decal->color4f[0][1] = c0[1];
11419         decal->color4f[0][2] = c0[2];
11420         decal->color4f[0][3] = 1;
11421         decal->color4f[1][0] = c1[0];
11422         decal->color4f[1][1] = c1[1];
11423         decal->color4f[1][2] = c1[2];
11424         decal->color4f[1][3] = 1;
11425         decal->color4f[2][0] = c2[0];
11426         decal->color4f[2][1] = c2[1];
11427         decal->color4f[2][2] = c2[2];
11428         decal->color4f[2][3] = 1;
11429         decal->vertex3f[0][0] = v0[0];
11430         decal->vertex3f[0][1] = v0[1];
11431         decal->vertex3f[0][2] = v0[2];
11432         decal->vertex3f[1][0] = v1[0];
11433         decal->vertex3f[1][1] = v1[1];
11434         decal->vertex3f[1][2] = v1[2];
11435         decal->vertex3f[2][0] = v2[0];
11436         decal->vertex3f[2][1] = v2[1];
11437         decal->vertex3f[2][2] = v2[2];
11438         decal->texcoord2f[0][0] = t0[0];
11439         decal->texcoord2f[0][1] = t0[1];
11440         decal->texcoord2f[1][0] = t1[0];
11441         decal->texcoord2f[1][1] = t1[1];
11442         decal->texcoord2f[2][0] = t2[0];
11443         decal->texcoord2f[2][1] = t2[1];
11444         TriangleNormal(v0, v1, v2, decal->plane);
11445         VectorNormalize(decal->plane);
11446         decal->plane[3] = DotProduct(v0, decal->plane);
11447 }
11448
11449 extern cvar_t cl_decals_bias;
11450 extern cvar_t cl_decals_models;
11451 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11452 // baseparms, parms, temps
11453 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)
11454 {
11455         int cornerindex;
11456         int index;
11457         float v[9][3];
11458         const float *vertex3f;
11459         const float *normal3f;
11460         int numpoints;
11461         float points[2][9][3];
11462         float temp[3];
11463         float tc[9][2];
11464         float f;
11465         float c[9][4];
11466         const int *e;
11467
11468         e = rsurface.modelelement3i + 3*triangleindex;
11469
11470         vertex3f = rsurface.modelvertex3f;
11471         normal3f = rsurface.modelnormal3f;
11472
11473         if (normal3f)
11474         {
11475                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11476                 {
11477                         index = 3*e[cornerindex];
11478                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11479                 }
11480         }
11481         else
11482         {
11483                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11484                 {
11485                         index = 3*e[cornerindex];
11486                         VectorCopy(vertex3f + index, v[cornerindex]);
11487                 }
11488         }
11489
11490         // cull backfaces
11491         //TriangleNormal(v[0], v[1], v[2], normal);
11492         //if (DotProduct(normal, localnormal) < 0.0f)
11493         //      continue;
11494         // clip by each of the box planes formed from the projection matrix
11495         // if anything survives, we emit the decal
11496         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]);
11497         if (numpoints < 3)
11498                 return;
11499         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]);
11500         if (numpoints < 3)
11501                 return;
11502         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]);
11503         if (numpoints < 3)
11504                 return;
11505         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]);
11506         if (numpoints < 3)
11507                 return;
11508         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]);
11509         if (numpoints < 3)
11510                 return;
11511         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]);
11512         if (numpoints < 3)
11513                 return;
11514         // some part of the triangle survived, so we have to accept it...
11515         if (dynamic)
11516         {
11517                 // dynamic always uses the original triangle
11518                 numpoints = 3;
11519                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11520                 {
11521                         index = 3*e[cornerindex];
11522                         VectorCopy(vertex3f + index, v[cornerindex]);
11523                 }
11524         }
11525         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11526         {
11527                 // convert vertex positions to texcoords
11528                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11529                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11530                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11531                 // calculate distance fade from the projection origin
11532                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11533                 f = bound(0.0f, f, 1.0f);
11534                 c[cornerindex][0] = r * f;
11535                 c[cornerindex][1] = g * f;
11536                 c[cornerindex][2] = b * f;
11537                 c[cornerindex][3] = 1.0f;
11538                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11539         }
11540         if (dynamic)
11541                 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);
11542         else
11543                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11544                         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);
11545 }
11546 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)
11547 {
11548         matrix4x4_t projection;
11549         decalsystem_t *decalsystem;
11550         qboolean dynamic;
11551         dp_model_t *model;
11552         const msurface_t *surface;
11553         const msurface_t *surfaces;
11554         const int *surfacelist;
11555         const texture_t *texture;
11556         int numtriangles;
11557         int numsurfacelist;
11558         int surfacelistindex;
11559         int surfaceindex;
11560         int triangleindex;
11561         float localorigin[3];
11562         float localnormal[3];
11563         float localmins[3];
11564         float localmaxs[3];
11565         float localsize;
11566         //float normal[3];
11567         float planes[6][4];
11568         float angles[3];
11569         bih_t *bih;
11570         int bih_triangles_count;
11571         int bih_triangles[256];
11572         int bih_surfaces[256];
11573
11574         decalsystem = &ent->decalsystem;
11575         model = ent->model;
11576         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11577         {
11578                 R_DecalSystem_Reset(&ent->decalsystem);
11579                 return;
11580         }
11581
11582         if (!model->brush.data_leafs && !cl_decals_models.integer)
11583         {
11584                 if (decalsystem->model)
11585                         R_DecalSystem_Reset(decalsystem);
11586                 return;
11587         }
11588
11589         if (decalsystem->model != model)
11590                 R_DecalSystem_Reset(decalsystem);
11591         decalsystem->model = model;
11592
11593         RSurf_ActiveModelEntity(ent, true, false, false);
11594
11595         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11596         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11597         VectorNormalize(localnormal);
11598         localsize = worldsize*rsurface.inversematrixscale;
11599         localmins[0] = localorigin[0] - localsize;
11600         localmins[1] = localorigin[1] - localsize;
11601         localmins[2] = localorigin[2] - localsize;
11602         localmaxs[0] = localorigin[0] + localsize;
11603         localmaxs[1] = localorigin[1] + localsize;
11604         localmaxs[2] = localorigin[2] + localsize;
11605
11606         //VectorCopy(localnormal, planes[4]);
11607         //VectorVectors(planes[4], planes[2], planes[0]);
11608         AnglesFromVectors(angles, localnormal, NULL, false);
11609         AngleVectors(angles, planes[0], planes[2], planes[4]);
11610         VectorNegate(planes[0], planes[1]);
11611         VectorNegate(planes[2], planes[3]);
11612         VectorNegate(planes[4], planes[5]);
11613         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11614         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11615         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11616         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11617         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11618         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11619
11620 #if 1
11621 // works
11622 {
11623         matrix4x4_t forwardprojection;
11624         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11625         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11626 }
11627 #else
11628 // broken
11629 {
11630         float projectionvector[4][3];
11631         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11632         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11633         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11634         projectionvector[0][0] = planes[0][0] * ilocalsize;
11635         projectionvector[0][1] = planes[1][0] * ilocalsize;
11636         projectionvector[0][2] = planes[2][0] * ilocalsize;
11637         projectionvector[1][0] = planes[0][1] * ilocalsize;
11638         projectionvector[1][1] = planes[1][1] * ilocalsize;
11639         projectionvector[1][2] = planes[2][1] * ilocalsize;
11640         projectionvector[2][0] = planes[0][2] * ilocalsize;
11641         projectionvector[2][1] = planes[1][2] * ilocalsize;
11642         projectionvector[2][2] = planes[2][2] * ilocalsize;
11643         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11644         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11645         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11646         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11647 }
11648 #endif
11649
11650         dynamic = model->surfmesh.isanimated;
11651         numsurfacelist = model->nummodelsurfaces;
11652         surfacelist = model->sortedmodelsurfaces;
11653         surfaces = model->data_surfaces;
11654
11655         bih = NULL;
11656         bih_triangles_count = -1;
11657         if(!dynamic)
11658         {
11659                 if(model->render_bih.numleafs)
11660                         bih = &model->render_bih;
11661                 else if(model->collision_bih.numleafs)
11662                         bih = &model->collision_bih;
11663         }
11664         if(bih)
11665                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11666         if(bih_triangles_count == 0)
11667                 return;
11668         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11669                 return;
11670         if(bih_triangles_count > 0)
11671         {
11672                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11673                 {
11674                         surfaceindex = bih_surfaces[triangleindex];
11675                         surface = surfaces + surfaceindex;
11676                         texture = surface->texture;
11677                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11678                                 continue;
11679                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11680                                 continue;
11681                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11682                 }
11683         }
11684         else
11685         {
11686                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11687                 {
11688                         surfaceindex = surfacelist[surfacelistindex];
11689                         surface = surfaces + surfaceindex;
11690                         // check cull box first because it rejects more than any other check
11691                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11692                                 continue;
11693                         // skip transparent surfaces
11694                         texture = surface->texture;
11695                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11696                                 continue;
11697                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11698                                 continue;
11699                         numtriangles = surface->num_triangles;
11700                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11701                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11702                 }
11703         }
11704 }
11705
11706 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11707 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)
11708 {
11709         int renderentityindex;
11710         float worldmins[3];
11711         float worldmaxs[3];
11712         entity_render_t *ent;
11713
11714         if (!cl_decals_newsystem.integer)
11715                 return;
11716
11717         worldmins[0] = worldorigin[0] - worldsize;
11718         worldmins[1] = worldorigin[1] - worldsize;
11719         worldmins[2] = worldorigin[2] - worldsize;
11720         worldmaxs[0] = worldorigin[0] + worldsize;
11721         worldmaxs[1] = worldorigin[1] + worldsize;
11722         worldmaxs[2] = worldorigin[2] + worldsize;
11723
11724         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11725
11726         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11727         {
11728                 ent = r_refdef.scene.entities[renderentityindex];
11729                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11730                         continue;
11731
11732                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11733         }
11734 }
11735
11736 typedef struct r_decalsystem_splatqueue_s
11737 {
11738         vec3_t worldorigin;
11739         vec3_t worldnormal;
11740         float color[4];
11741         float tcrange[4];
11742         float worldsize;
11743         unsigned int decalsequence;
11744 }
11745 r_decalsystem_splatqueue_t;
11746
11747 int r_decalsystem_numqueued = 0;
11748 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11749
11750 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)
11751 {
11752         r_decalsystem_splatqueue_t *queue;
11753
11754         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11755                 return;
11756
11757         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11758         VectorCopy(worldorigin, queue->worldorigin);
11759         VectorCopy(worldnormal, queue->worldnormal);
11760         Vector4Set(queue->color, r, g, b, a);
11761         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11762         queue->worldsize = worldsize;
11763         queue->decalsequence = cl.decalsequence++;
11764 }
11765
11766 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11767 {
11768         int i;
11769         r_decalsystem_splatqueue_t *queue;
11770
11771         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11772                 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);
11773         r_decalsystem_numqueued = 0;
11774 }
11775
11776 extern cvar_t cl_decals_max;
11777 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11778 {
11779         int i;
11780         decalsystem_t *decalsystem = &ent->decalsystem;
11781         int numdecals;
11782         unsigned int killsequence;
11783         tridecal_t *decal;
11784         float frametime;
11785         float lifetime;
11786
11787         if (!decalsystem->numdecals)
11788                 return;
11789
11790         if (r_showsurfaces.integer)
11791                 return;
11792
11793         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11794         {
11795                 R_DecalSystem_Reset(decalsystem);
11796                 return;
11797         }
11798
11799         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11800         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11801
11802         if (decalsystem->lastupdatetime)
11803                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11804         else
11805                 frametime = 0;
11806         decalsystem->lastupdatetime = r_refdef.scene.time;
11807         numdecals = decalsystem->numdecals;
11808
11809         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11810         {
11811                 if (decal->color4f[0][3])
11812                 {
11813                         decal->lived += frametime;
11814                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11815                         {
11816                                 memset(decal, 0, sizeof(*decal));
11817                                 if (decalsystem->freedecal > i)
11818                                         decalsystem->freedecal = i;
11819                         }
11820                 }
11821         }
11822         decal = decalsystem->decals;
11823         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11824                 numdecals--;
11825
11826         // collapse the array by shuffling the tail decals into the gaps
11827         for (;;)
11828         {
11829                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11830                         decalsystem->freedecal++;
11831                 if (decalsystem->freedecal == numdecals)
11832                         break;
11833                 decal[decalsystem->freedecal] = decal[--numdecals];
11834         }
11835
11836         decalsystem->numdecals = numdecals;
11837
11838         if (numdecals <= 0)
11839         {
11840                 // if there are no decals left, reset decalsystem
11841                 R_DecalSystem_Reset(decalsystem);
11842         }
11843 }
11844
11845 extern skinframe_t *decalskinframe;
11846 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11847 {
11848         int i;
11849         decalsystem_t *decalsystem = &ent->decalsystem;
11850         int numdecals;
11851         tridecal_t *decal;
11852         float faderate;
11853         float alpha;
11854         float *v3f;
11855         float *c4f;
11856         float *t2f;
11857         const int *e;
11858         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11859         int numtris = 0;
11860
11861         numdecals = decalsystem->numdecals;
11862         if (!numdecals)
11863                 return;
11864
11865         if (r_showsurfaces.integer)
11866                 return;
11867
11868         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11869         {
11870                 R_DecalSystem_Reset(decalsystem);
11871                 return;
11872         }
11873
11874         // if the model is static it doesn't matter what value we give for
11875         // wantnormals and wanttangents, so this logic uses only rules applicable
11876         // to a model, knowing that they are meaningless otherwise
11877         RSurf_ActiveModelEntity(ent, false, false, false);
11878
11879         decalsystem->lastupdatetime = r_refdef.scene.time;
11880
11881         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11882
11883         // update vertex positions for animated models
11884         v3f = decalsystem->vertex3f;
11885         c4f = decalsystem->color4f;
11886         t2f = decalsystem->texcoord2f;
11887         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11888         {
11889                 if (!decal->color4f[0][3])
11890                         continue;
11891
11892                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11893                         continue;
11894
11895                 // skip backfaces
11896                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11897                         continue;
11898
11899                 // update color values for fading decals
11900                 if (decal->lived >= cl_decals_time.value)
11901                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11902                 else
11903                         alpha = 1.0f;
11904
11905                 c4f[ 0] = decal->color4f[0][0] * alpha;
11906                 c4f[ 1] = decal->color4f[0][1] * alpha;
11907                 c4f[ 2] = decal->color4f[0][2] * alpha;
11908                 c4f[ 3] = 1;
11909                 c4f[ 4] = decal->color4f[1][0] * alpha;
11910                 c4f[ 5] = decal->color4f[1][1] * alpha;
11911                 c4f[ 6] = decal->color4f[1][2] * alpha;
11912                 c4f[ 7] = 1;
11913                 c4f[ 8] = decal->color4f[2][0] * alpha;
11914                 c4f[ 9] = decal->color4f[2][1] * alpha;
11915                 c4f[10] = decal->color4f[2][2] * alpha;
11916                 c4f[11] = 1;
11917
11918                 t2f[0] = decal->texcoord2f[0][0];
11919                 t2f[1] = decal->texcoord2f[0][1];
11920                 t2f[2] = decal->texcoord2f[1][0];
11921                 t2f[3] = decal->texcoord2f[1][1];
11922                 t2f[4] = decal->texcoord2f[2][0];
11923                 t2f[5] = decal->texcoord2f[2][1];
11924
11925                 // update vertex positions for animated models
11926                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11927                 {
11928                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11929                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11930                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11931                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11932                 }
11933                 else
11934                 {
11935                         VectorCopy(decal->vertex3f[0], v3f);
11936                         VectorCopy(decal->vertex3f[1], v3f + 3);
11937                         VectorCopy(decal->vertex3f[2], v3f + 6);
11938                 }
11939
11940                 if (r_refdef.fogenabled)
11941                 {
11942                         alpha = RSurf_FogVertex(v3f);
11943                         VectorScale(c4f, alpha, c4f);
11944                         alpha = RSurf_FogVertex(v3f + 3);
11945                         VectorScale(c4f + 4, alpha, c4f + 4);
11946                         alpha = RSurf_FogVertex(v3f + 6);
11947                         VectorScale(c4f + 8, alpha, c4f + 8);
11948                 }
11949
11950                 v3f += 9;
11951                 c4f += 12;
11952                 t2f += 6;
11953                 numtris++;
11954         }
11955
11956         if (numtris > 0)
11957         {
11958                 r_refdef.stats[r_stat_drawndecals] += numtris;
11959
11960                 // now render the decals all at once
11961                 // (this assumes they all use one particle font texture!)
11962                 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);
11963 //              R_Mesh_ResetTextureState();
11964                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11965                 GL_DepthMask(false);
11966                 GL_DepthRange(0, 1);
11967                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11968                 GL_DepthTest(true);
11969                 GL_CullFace(GL_NONE);
11970                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11971                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11972                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11973         }
11974 }
11975
11976 static void R_DrawModelDecals(void)
11977 {
11978         int i, numdecals;
11979
11980         // fade faster when there are too many decals
11981         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11982         for (i = 0;i < r_refdef.scene.numentities;i++)
11983                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11984
11985         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11986         for (i = 0;i < r_refdef.scene.numentities;i++)
11987                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11988                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11989
11990         R_DecalSystem_ApplySplatEntitiesQueue();
11991
11992         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11993         for (i = 0;i < r_refdef.scene.numentities;i++)
11994                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11995
11996         r_refdef.stats[r_stat_totaldecals] += numdecals;
11997
11998         if (r_showsurfaces.integer)
11999                 return;
12000
12001         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12002
12003         for (i = 0;i < r_refdef.scene.numentities;i++)
12004         {
12005                 if (!r_refdef.viewcache.entityvisible[i])
12006                         continue;
12007                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12008                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12009         }
12010 }
12011
12012 extern cvar_t mod_collision_bih;
12013 static void R_DrawDebugModel(void)
12014 {
12015         entity_render_t *ent = rsurface.entity;
12016         int i, j, flagsmask;
12017         const msurface_t *surface;
12018         dp_model_t *model = ent->model;
12019
12020         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12021                 return;
12022
12023         if (r_showoverdraw.value > 0)
12024         {
12025                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12026                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12027                 R_SetupShader_Generic_NoTexture(false, false);
12028                 GL_DepthTest(false);
12029                 GL_DepthMask(false);
12030                 GL_DepthRange(0, 1);
12031                 GL_BlendFunc(GL_ONE, GL_ONE);
12032                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12033                 {
12034                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12035                                 continue;
12036                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12037                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12038                         {
12039                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12040                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12041                                 if (!rsurface.texture->currentlayers->depthmask)
12042                                         GL_Color(c, 0, 0, 1.0f);
12043                                 else if (ent == r_refdef.scene.worldentity)
12044                                         GL_Color(c, c, c, 1.0f);
12045                                 else
12046                                         GL_Color(0, c, 0, 1.0f);
12047                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12048                                 RSurf_DrawBatch();
12049                         }
12050                 }
12051                 rsurface.texture = NULL;
12052         }
12053
12054         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12055
12056 //      R_Mesh_ResetTextureState();
12057         R_SetupShader_Generic_NoTexture(false, false);
12058         GL_DepthRange(0, 1);
12059         GL_DepthTest(!r_showdisabledepthtest.integer);
12060         GL_DepthMask(false);
12061         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12062
12063         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12064         {
12065                 int triangleindex;
12066                 int bihleafindex;
12067                 qboolean cullbox = false;
12068                 const q3mbrush_t *brush;
12069                 const bih_t *bih = &model->collision_bih;
12070                 const bih_leaf_t *bihleaf;
12071                 float vertex3f[3][3];
12072                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12073                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12074                 {
12075                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12076                                 continue;
12077                         switch (bihleaf->type)
12078                         {
12079                         case BIH_BRUSH:
12080                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12081                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12082                                 {
12083                                         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);
12084                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12085                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12086                                 }
12087                                 break;
12088                         case BIH_COLLISIONTRIANGLE:
12089                                 triangleindex = bihleaf->itemindex;
12090                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12091                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12092                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12093                                 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);
12094                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12095                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12096                                 break;
12097                         case BIH_RENDERTRIANGLE:
12098                                 triangleindex = bihleaf->itemindex;
12099                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12100                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12101                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12102                                 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);
12103                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12104                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12105                                 break;
12106                         }
12107                 }
12108         }
12109
12110         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12111
12112 #ifndef USE_GLES2
12113         if (r_showtris.integer && qglPolygonMode)
12114         {
12115                 if (r_showdisabledepthtest.integer)
12116                 {
12117                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12118                         GL_DepthMask(false);
12119                 }
12120                 else
12121                 {
12122                         GL_BlendFunc(GL_ONE, GL_ZERO);
12123                         GL_DepthMask(true);
12124                 }
12125                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12126                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12127                 {
12128                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12129                                 continue;
12130                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12131                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12132                         {
12133                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12134                                 if (!rsurface.texture->currentlayers->depthmask)
12135                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12136                                 else if (ent == r_refdef.scene.worldentity)
12137                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12138                                 else
12139                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12140                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12141                                 RSurf_DrawBatch();
12142                         }
12143                 }
12144                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12145                 rsurface.texture = NULL;
12146         }
12147
12148         if (r_shownormals.value != 0 && qglBegin)
12149         {
12150                 int l, k;
12151                 vec3_t v;
12152                 if (r_showdisabledepthtest.integer)
12153                 {
12154                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12155                         GL_DepthMask(false);
12156                 }
12157                 else
12158                 {
12159                         GL_BlendFunc(GL_ONE, GL_ZERO);
12160                         GL_DepthMask(true);
12161                 }
12162                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12163                 {
12164                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12165                                 continue;
12166                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12167                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12168                         {
12169                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12170                                 qglBegin(GL_LINES);
12171                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12172                                 {
12173                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12174                                         {
12175                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12176                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12177                                                 qglVertex3f(v[0], v[1], v[2]);
12178                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12179                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12180                                                 qglVertex3f(v[0], v[1], v[2]);
12181                                         }
12182                                 }
12183                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12184                                 {
12185                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12186                                         {
12187                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12188                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12189                                                 qglVertex3f(v[0], v[1], v[2]);
12190                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12191                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12192                                                 qglVertex3f(v[0], v[1], v[2]);
12193                                         }
12194                                 }
12195                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12196                                 {
12197                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12198                                         {
12199                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12200                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12201                                                 qglVertex3f(v[0], v[1], v[2]);
12202                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12203                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12204                                                 qglVertex3f(v[0], v[1], v[2]);
12205                                         }
12206                                 }
12207                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12208                                 {
12209                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12210                                         {
12211                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12212                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12213                                                 qglVertex3f(v[0], v[1], v[2]);
12214                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12215                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12216                                                 qglVertex3f(v[0], v[1], v[2]);
12217                                         }
12218                                 }
12219                                 qglEnd();
12220                                 CHECKGLERROR
12221                         }
12222                 }
12223                 rsurface.texture = NULL;
12224         }
12225 #endif
12226 }
12227
12228 int r_maxsurfacelist = 0;
12229 const msurface_t **r_surfacelist = NULL;
12230 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12231 {
12232         int i, j, endj, flagsmask;
12233         dp_model_t *model = ent->model;
12234         msurface_t *surfaces;
12235         unsigned char *update;
12236         int numsurfacelist = 0;
12237         if (model == NULL)
12238                 return;
12239
12240         if (r_maxsurfacelist < model->num_surfaces)
12241         {
12242                 r_maxsurfacelist = model->num_surfaces;
12243                 if (r_surfacelist)
12244                         Mem_Free((msurface_t **)r_surfacelist);
12245                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12246         }
12247
12248         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12249                 RSurf_ActiveModelEntity(ent, false, false, false);
12250         else if (prepass)
12251                 RSurf_ActiveModelEntity(ent, true, true, true);
12252         else if (depthonly)
12253         {
12254                 switch (vid.renderpath)
12255                 {
12256                 case RENDERPATH_GL20:
12257                 case RENDERPATH_D3D9:
12258                 case RENDERPATH_D3D10:
12259                 case RENDERPATH_D3D11:
12260                 case RENDERPATH_SOFT:
12261                 case RENDERPATH_GLES2:
12262                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12263                         break;
12264                 case RENDERPATH_GL11:
12265                 case RENDERPATH_GL13:
12266                 case RENDERPATH_GLES1:
12267                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12268                         break;
12269                 }
12270         }
12271         else
12272         {
12273                 switch (vid.renderpath)
12274                 {
12275                 case RENDERPATH_GL20:
12276                 case RENDERPATH_D3D9:
12277                 case RENDERPATH_D3D10:
12278                 case RENDERPATH_D3D11:
12279                 case RENDERPATH_SOFT:
12280                 case RENDERPATH_GLES2:
12281                         RSurf_ActiveModelEntity(ent, true, true, false);
12282                         break;
12283                 case RENDERPATH_GL11:
12284                 case RENDERPATH_GL13:
12285                 case RENDERPATH_GLES1:
12286                         RSurf_ActiveModelEntity(ent, true, false, false);
12287                         break;
12288                 }
12289         }
12290
12291         surfaces = model->data_surfaces;
12292         update = model->brushq1.lightmapupdateflags;
12293
12294         // update light styles
12295         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12296         {
12297                 model_brush_lightstyleinfo_t *style;
12298                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12299                 {
12300                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12301                         {
12302                                 int *list = style->surfacelist;
12303                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12304                                 for (j = 0;j < style->numsurfaces;j++)
12305                                         update[list[j]] = true;
12306                         }
12307                 }
12308         }
12309
12310         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12311
12312         if (debug)
12313         {
12314                 R_DrawDebugModel();
12315                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12316                 return;
12317         }
12318
12319         rsurface.lightmaptexture = NULL;
12320         rsurface.deluxemaptexture = NULL;
12321         rsurface.uselightmaptexture = false;
12322         rsurface.texture = NULL;
12323         rsurface.rtlight = NULL;
12324         numsurfacelist = 0;
12325         // add visible surfaces to draw list
12326         if (ent == r_refdef.scene.worldentity)
12327         {
12328                 // for the world entity, check surfacevisible
12329                 for (i = 0;i < model->nummodelsurfaces;i++)
12330                 {
12331                         j = model->sortedmodelsurfaces[i];
12332                         if (r_refdef.viewcache.world_surfacevisible[j])
12333                                 r_surfacelist[numsurfacelist++] = surfaces + j;
12334                 }
12335         }
12336         else
12337         {
12338                 // add all surfaces
12339                 for (i = 0; i < model->nummodelsurfaces; i++)
12340                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12341         }
12342         // don't do anything if there were no surfaces
12343         if (!numsurfacelist)
12344         {
12345                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12346                 return;
12347         }
12348         // update lightmaps if needed
12349         if (update)
12350         {
12351                 int updated = 0;
12352                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12353                 {
12354                         if (update[j])
12355                         {
12356                                 updated++;
12357                                 R_BuildLightMap(ent, surfaces + j);
12358                         }
12359                 }
12360         }
12361
12362         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12363
12364         // add to stats if desired
12365         if (r_speeds.integer && !skysurfaces && !depthonly)
12366         {
12367                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12368                 for (j = 0;j < numsurfacelist;j++)
12369                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12370         }
12371
12372         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12373 }
12374
12375 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12376 {
12377         int q;
12378         static texture_t texture;
12379         static msurface_t surface;
12380         const msurface_t *surfacelist = &surface;
12381
12382         // fake enough texture and surface state to render this geometry
12383
12384         texture.update_lastrenderframe = -1; // regenerate this texture
12385         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12386         texture.basealpha = 1.0f;
12387         texture.currentskinframe = skinframe;
12388         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12389         texture.offsetmapping = OFFSETMAPPING_OFF;
12390         texture.offsetscale = 1;
12391         texture.specularscalemod = 1;
12392         texture.specularpowermod = 1;
12393         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12394         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12395         // JUST GREP FOR "specularscalemod = 1".
12396
12397         for (q = 0; q < 3; q++)
12398         {
12399                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12400                 texture.render_modellight_lightdir[q] = q == 2;
12401                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12402                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12403                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12404                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12405                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12406                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12407                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12408                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12409         }
12410         texture.currentalpha = 1.0f;
12411
12412         surface.texture = &texture;
12413         surface.num_triangles = numtriangles;
12414         surface.num_firsttriangle = firsttriangle;
12415         surface.num_vertices = numvertices;
12416         surface.num_firstvertex = firstvertex;
12417
12418         // now render it
12419         rsurface.texture = R_GetCurrentTexture(surface.texture);
12420         rsurface.lightmaptexture = NULL;
12421         rsurface.deluxemaptexture = NULL;
12422         rsurface.uselightmaptexture = false;
12423         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12424 }
12425
12426 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)
12427 {
12428         static msurface_t surface;
12429         const msurface_t *surfacelist = &surface;
12430
12431         // fake enough texture and surface state to render this geometry
12432         surface.texture = texture;
12433         surface.num_triangles = numtriangles;
12434         surface.num_firsttriangle = firsttriangle;
12435         surface.num_vertices = numvertices;
12436         surface.num_firstvertex = firstvertex;
12437
12438         // now render it
12439         rsurface.texture = R_GetCurrentTexture(surface.texture);
12440         rsurface.lightmaptexture = NULL;
12441         rsurface.deluxemaptexture = NULL;
12442         rsurface.uselightmaptexture = false;
12443         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12444 }