]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Add a cvar: r_water_cameraentitiesonly.
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47 static qboolean r_gpuskeletal;
48
49 //
50 // screen size info
51 //
52 r_refdef_t r_refdef;
53
54 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!"};
55 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!"};
56 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
57 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
58 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)"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
60 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"};
61 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"};
62 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"};
63 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"};
64 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"};
65 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"};
66
67 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
68 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"};
69 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
70 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)"};
71 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
72
73 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"};
74 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
75 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
76 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
77 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
78 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
79 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
80 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"};
81 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"};
82 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"};
83 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
84 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
85 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)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 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"};
89 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"};
90 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
91 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"};
92 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"};
93 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"};
94 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
95 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
96 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
97 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
98 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
99 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
100 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
101 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)"};
102 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)"};
103 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
104 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
105 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
106 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
107 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
108
109 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
110 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
111 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
112
113 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
114 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
115 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
116 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."};
117 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
118 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
119 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
120 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."};
121 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
122 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
123 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
124 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."};
125 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
126 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"};
127 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"};
128 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
130 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
131 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
132 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
133 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"};
134 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
135 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
136 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
137 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
138 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
139
140 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
141 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
142 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
143 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
144 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
145 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
146 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
147 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
148
149 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)"};
150 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"};
151
152 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
153 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
154 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
155
156 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"};
157 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"};
158 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"};
159 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
160 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
161 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"};
162 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)"};
163 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)"};
164 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
165
166 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
167 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)"};
168 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
169 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)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
171 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)"};
172 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)"};
173 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
174 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"};
175 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."};
176 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183 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)"};
184 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)"};
185
186 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)"};
187 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)"};
188 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
189 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"};
190 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
191 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
192 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
193 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"};
194 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"};
195 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)"};
196
197 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
198 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
199 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
200 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
201
202 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
203 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
204
205 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
206 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
207 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
208 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
209 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
210 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
211
212 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
213 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
214 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
215 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
216 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
218 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
219 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
220 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
221 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
222
223 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"};
224
225 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"};
226
227 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
228
229 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
230
231 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)"};
232 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)"};
233 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
234 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
235
236 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
237 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"};
238
239 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."};
240
241 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)"};
242 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
243 {
244         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
245         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
246         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
247         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
248 };
249
250 extern cvar_t v_glslgamma;
251 extern cvar_t v_glslgamma_2d;
252
253 extern qboolean v_flipped_state;
254
255 r_framebufferstate_t r_fb;
256
257 /// shadow volume bsp struct with automatically growing nodes buffer
258 svbsp_t r_svbsp;
259
260 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
261
262 rtexture_t *r_texture_blanknormalmap;
263 rtexture_t *r_texture_white;
264 rtexture_t *r_texture_grey128;
265 rtexture_t *r_texture_black;
266 rtexture_t *r_texture_notexture;
267 rtexture_t *r_texture_whitecube;
268 rtexture_t *r_texture_normalizationcube;
269 rtexture_t *r_texture_fogattenuation;
270 rtexture_t *r_texture_fogheighttexture;
271 rtexture_t *r_texture_gammaramps;
272 unsigned int r_texture_gammaramps_serial;
273 //rtexture_t *r_texture_fogintensity;
274 rtexture_t *r_texture_reflectcube;
275
276 // TODO: hash lookups?
277 typedef struct cubemapinfo_s
278 {
279         char basename[64];
280         rtexture_t *texture;
281 }
282 cubemapinfo_t;
283
284 int r_texture_numcubemaps;
285 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
286
287 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
288 unsigned int r_numqueries;
289 unsigned int r_maxqueries;
290
291 typedef struct r_qwskincache_s
292 {
293         char name[MAX_QPATH];
294         skinframe_t *skinframe;
295 }
296 r_qwskincache_t;
297
298 static r_qwskincache_t *r_qwskincache;
299 static int r_qwskincache_size;
300
301 /// vertex coordinates for a quad that covers the screen exactly
302 extern const float r_screenvertex3f[12];
303 extern const float r_d3dscreenvertex3f[12];
304 const float r_screenvertex3f[12] =
305 {
306         0, 0, 0,
307         1, 0, 0,
308         1, 1, 0,
309         0, 1, 0
310 };
311 const float r_d3dscreenvertex3f[12] =
312 {
313         0, 1, 0,
314         1, 1, 0,
315         1, 0, 0,
316         0, 0, 0
317 };
318
319 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
320 {
321         int i;
322         for (i = 0;i < verts;i++)
323         {
324                 out[0] = in[0] * r;
325                 out[1] = in[1] * g;
326                 out[2] = in[2] * b;
327                 out[3] = in[3];
328                 in += 4;
329                 out += 4;
330         }
331 }
332
333 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
334 {
335         int i;
336         for (i = 0;i < verts;i++)
337         {
338                 out[0] = r;
339                 out[1] = g;
340                 out[2] = b;
341                 out[3] = a;
342                 out += 4;
343         }
344 }
345
346 // FIXME: move this to client?
347 void FOG_clear(void)
348 {
349         if (gamemode == GAME_NEHAHRA)
350         {
351                 Cvar_Set("gl_fogenable", "0");
352                 Cvar_Set("gl_fogdensity", "0.2");
353                 Cvar_Set("gl_fogred", "0.3");
354                 Cvar_Set("gl_foggreen", "0.3");
355                 Cvar_Set("gl_fogblue", "0.3");
356         }
357         r_refdef.fog_density = 0;
358         r_refdef.fog_red = 0;
359         r_refdef.fog_green = 0;
360         r_refdef.fog_blue = 0;
361         r_refdef.fog_alpha = 1;
362         r_refdef.fog_start = 0;
363         r_refdef.fog_end = 16384;
364         r_refdef.fog_height = 1<<30;
365         r_refdef.fog_fadedepth = 128;
366         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
367 }
368
369 static void R_BuildBlankTextures(void)
370 {
371         unsigned char data[4];
372         data[2] = 128; // normal X
373         data[1] = 128; // normal Y
374         data[0] = 255; // normal Z
375         data[3] = 255; // height
376         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
377         data[0] = 255;
378         data[1] = 255;
379         data[2] = 255;
380         data[3] = 255;
381         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
382         data[0] = 128;
383         data[1] = 128;
384         data[2] = 128;
385         data[3] = 255;
386         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387         data[0] = 0;
388         data[1] = 0;
389         data[2] = 0;
390         data[3] = 255;
391         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 }
393
394 static void R_BuildNoTexture(void)
395 {
396         int x, y;
397         unsigned char pix[16][16][4];
398         // this makes a light grey/dark grey checkerboard texture
399         for (y = 0;y < 16;y++)
400         {
401                 for (x = 0;x < 16;x++)
402                 {
403                         if ((y < 8) ^ (x < 8))
404                         {
405                                 pix[y][x][0] = 128;
406                                 pix[y][x][1] = 128;
407                                 pix[y][x][2] = 128;
408                                 pix[y][x][3] = 255;
409                         }
410                         else
411                         {
412                                 pix[y][x][0] = 64;
413                                 pix[y][x][1] = 64;
414                                 pix[y][x][2] = 64;
415                                 pix[y][x][3] = 255;
416                         }
417                 }
418         }
419         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
420 }
421
422 static void R_BuildWhiteCube(void)
423 {
424         unsigned char data[6*1*1*4];
425         memset(data, 255, sizeof(data));
426         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
427 }
428
429 static void R_BuildNormalizationCube(void)
430 {
431         int x, y, side;
432         vec3_t v;
433         vec_t s, t, intensity;
434 #define NORMSIZE 64
435         unsigned char *data;
436         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
437         for (side = 0;side < 6;side++)
438         {
439                 for (y = 0;y < NORMSIZE;y++)
440                 {
441                         for (x = 0;x < NORMSIZE;x++)
442                         {
443                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
445                                 switch(side)
446                                 {
447                                 default:
448                                 case 0:
449                                         v[0] = 1;
450                                         v[1] = -t;
451                                         v[2] = -s;
452                                         break;
453                                 case 1:
454                                         v[0] = -1;
455                                         v[1] = -t;
456                                         v[2] = s;
457                                         break;
458                                 case 2:
459                                         v[0] = s;
460                                         v[1] = 1;
461                                         v[2] = t;
462                                         break;
463                                 case 3:
464                                         v[0] = s;
465                                         v[1] = -1;
466                                         v[2] = -t;
467                                         break;
468                                 case 4:
469                                         v[0] = s;
470                                         v[1] = -t;
471                                         v[2] = 1;
472                                         break;
473                                 case 5:
474                                         v[0] = -s;
475                                         v[1] = -t;
476                                         v[2] = -1;
477                                         break;
478                                 }
479                                 intensity = 127.0f / sqrt(DotProduct(v, v));
480                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
481                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
482                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
483                                 data[((side*64+y)*64+x)*4+3] = 255;
484                         }
485                 }
486         }
487         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
488         Mem_Free(data);
489 }
490
491 static void R_BuildFogTexture(void)
492 {
493         int x, b;
494 #define FOGWIDTH 256
495         unsigned char data1[FOGWIDTH][4];
496         //unsigned char data2[FOGWIDTH][4];
497         double d, r, alpha;
498
499         r_refdef.fogmasktable_start = r_refdef.fog_start;
500         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
501         r_refdef.fogmasktable_range = r_refdef.fogrange;
502         r_refdef.fogmasktable_density = r_refdef.fog_density;
503
504         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
505         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506         {
507                 d = (x * r - r_refdef.fogmasktable_start);
508                 if(developer_extra.integer)
509                         Con_DPrintf("%f ", d);
510                 d = max(0, d);
511                 if (r_fog_exp2.integer)
512                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513                 else
514                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
515                 if(developer_extra.integer)
516                         Con_DPrintf(" : %f ", alpha);
517                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
518                 if(developer_extra.integer)
519                         Con_DPrintf(" = %f\n", alpha);
520                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
521         }
522
523         for (x = 0;x < FOGWIDTH;x++)
524         {
525                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
526                 data1[x][0] = b;
527                 data1[x][1] = b;
528                 data1[x][2] = b;
529                 data1[x][3] = 255;
530                 //data2[x][0] = 255 - b;
531                 //data2[x][1] = 255 - b;
532                 //data2[x][2] = 255 - b;
533                 //data2[x][3] = 255;
534         }
535         if (r_texture_fogattenuation)
536         {
537                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
539         }
540         else
541         {
542                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
543                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
544         }
545 }
546
547 static void R_BuildFogHeightTexture(void)
548 {
549         unsigned char *inpixels;
550         int size;
551         int x;
552         int y;
553         int j;
554         float c[4];
555         float f;
556         inpixels = NULL;
557         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
558         if (r_refdef.fogheighttexturename[0])
559                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
560         if (!inpixels)
561         {
562                 r_refdef.fog_height_tablesize = 0;
563                 if (r_texture_fogheighttexture)
564                         R_FreeTexture(r_texture_fogheighttexture);
565                 r_texture_fogheighttexture = NULL;
566                 if (r_refdef.fog_height_table2d)
567                         Mem_Free(r_refdef.fog_height_table2d);
568                 r_refdef.fog_height_table2d = NULL;
569                 if (r_refdef.fog_height_table1d)
570                         Mem_Free(r_refdef.fog_height_table1d);
571                 r_refdef.fog_height_table1d = NULL;
572                 return;
573         }
574         size = image_width;
575         r_refdef.fog_height_tablesize = size;
576         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
577         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
578         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579         Mem_Free(inpixels);
580         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
581         // average fog color table accounting for every fog layer between a point
582         // and the camera.  (Note: attenuation is handled separately!)
583         for (y = 0;y < size;y++)
584         {
585                 for (x = 0;x < size;x++)
586                 {
587                         Vector4Clear(c);
588                         f = 0;
589                         if (x < y)
590                         {
591                                 for (j = x;j <= y;j++)
592                                 {
593                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
594                                         f++;
595                                 }
596                         }
597                         else
598                         {
599                                 for (j = x;j >= y;j--)
600                                 {
601                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
602                                         f++;
603                                 }
604                         }
605                         f = 1.0f / f;
606                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
609                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
610                 }
611         }
612         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
613 }
614
615 //=======================================================================================================================================================
616
617 static const char *builtinshaderstrings[] =
618 {
619 #include "shader_glsl.h"
620 0
621 };
622
623 const char *builtinhlslshaderstrings[] =
624 {
625 #include "shader_hlsl.h"
626 0
627 };
628
629 char *glslshaderstring = NULL;
630 char *hlslshaderstring = NULL;
631
632 //=======================================================================================================================================================
633
634 typedef struct shaderpermutationinfo_s
635 {
636         const char *pretext;
637         const char *name;
638 }
639 shaderpermutationinfo_t;
640
641 typedef struct shadermodeinfo_s
642 {
643         const char *filename;
644         const char *pretext;
645         const char *name;
646 }
647 shadermodeinfo_t;
648
649 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
650 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
651 {
652         {"#define USEDIFFUSE\n", " diffuse"},
653         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
654         {"#define USEVIEWTINT\n", " viewtint"},
655         {"#define USECOLORMAPPING\n", " colormapping"},
656         {"#define USESATURATION\n", " saturation"},
657         {"#define USEFOGINSIDE\n", " foginside"},
658         {"#define USEFOGOUTSIDE\n", " fogoutside"},
659         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
660         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
661         {"#define USEGAMMARAMPS\n", " gammaramps"},
662         {"#define USECUBEFILTER\n", " cubefilter"},
663         {"#define USEGLOW\n", " glow"},
664         {"#define USEBLOOM\n", " bloom"},
665         {"#define USESPECULAR\n", " specular"},
666         {"#define USEPOSTPROCESSING\n", " postprocessing"},
667         {"#define USEREFLECTION\n", " reflection"},
668         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
669         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
670         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
671         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
672         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674         {"#define USEALPHAKILL\n", " alphakill"},
675         {"#define USEREFLECTCUBE\n", " reflectcube"},
676         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677         {"#define USEBOUNCEGRID\n", " bouncegrid"},
678         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
679         {"#define USETRIPPY\n", " trippy"},
680         {"#define USEDEPTHRGB\n", " depthrgb"},
681         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
682         {"#define USESKELETAL\n", " skeletal"},
683         {"#define USEOCCLUDE\n", " occlude"}
684 };
685
686 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
687 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
688 {
689         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
690         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
691         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
692         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
693         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
694         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
695         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
696         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
697         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
698         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
699         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
700         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
701         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
702         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
703         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
704         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
705         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 };
707
708 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
709 {
710         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
711         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
712         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
713         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
714         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
715         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
716         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
717         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
718         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
719         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
720         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
721         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
722         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
723         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
724         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
725         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
726         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
727 };
728
729 struct r_glsl_permutation_s;
730 typedef struct r_glsl_permutation_s
731 {
732         /// hash lookup data
733         struct r_glsl_permutation_s *hashnext;
734         unsigned int mode;
735         unsigned int permutation;
736
737         /// indicates if we have tried compiling this permutation already
738         qboolean compiled;
739         /// 0 if compilation failed
740         int program;
741         // texture units assigned to each detected uniform
742         int tex_Texture_First;
743         int tex_Texture_Second;
744         int tex_Texture_GammaRamps;
745         int tex_Texture_Normal;
746         int tex_Texture_Color;
747         int tex_Texture_Gloss;
748         int tex_Texture_Glow;
749         int tex_Texture_SecondaryNormal;
750         int tex_Texture_SecondaryColor;
751         int tex_Texture_SecondaryGloss;
752         int tex_Texture_SecondaryGlow;
753         int tex_Texture_Pants;
754         int tex_Texture_Shirt;
755         int tex_Texture_FogHeightTexture;
756         int tex_Texture_FogMask;
757         int tex_Texture_Lightmap;
758         int tex_Texture_Deluxemap;
759         int tex_Texture_Attenuation;
760         int tex_Texture_Cube;
761         int tex_Texture_Refraction;
762         int tex_Texture_Reflection;
763         int tex_Texture_ShadowMap2D;
764         int tex_Texture_CubeProjection;
765         int tex_Texture_ScreenNormalMap;
766         int tex_Texture_ScreenDiffuse;
767         int tex_Texture_ScreenSpecular;
768         int tex_Texture_ReflectMask;
769         int tex_Texture_ReflectCube;
770         int tex_Texture_BounceGrid;
771         /// locations of detected uniforms in program object, or -1 if not found
772         int loc_Texture_First;
773         int loc_Texture_Second;
774         int loc_Texture_GammaRamps;
775         int loc_Texture_Normal;
776         int loc_Texture_Color;
777         int loc_Texture_Gloss;
778         int loc_Texture_Glow;
779         int loc_Texture_SecondaryNormal;
780         int loc_Texture_SecondaryColor;
781         int loc_Texture_SecondaryGloss;
782         int loc_Texture_SecondaryGlow;
783         int loc_Texture_Pants;
784         int loc_Texture_Shirt;
785         int loc_Texture_FogHeightTexture;
786         int loc_Texture_FogMask;
787         int loc_Texture_Lightmap;
788         int loc_Texture_Deluxemap;
789         int loc_Texture_Attenuation;
790         int loc_Texture_Cube;
791         int loc_Texture_Refraction;
792         int loc_Texture_Reflection;
793         int loc_Texture_ShadowMap2D;
794         int loc_Texture_CubeProjection;
795         int loc_Texture_ScreenNormalMap;
796         int loc_Texture_ScreenDiffuse;
797         int loc_Texture_ScreenSpecular;
798         int loc_Texture_ReflectMask;
799         int loc_Texture_ReflectCube;
800         int loc_Texture_BounceGrid;
801         int loc_Alpha;
802         int loc_BloomBlur_Parameters;
803         int loc_ClientTime;
804         int loc_Color_Ambient;
805         int loc_Color_Diffuse;
806         int loc_Color_Specular;
807         int loc_Color_Glow;
808         int loc_Color_Pants;
809         int loc_Color_Shirt;
810         int loc_DeferredColor_Ambient;
811         int loc_DeferredColor_Diffuse;
812         int loc_DeferredColor_Specular;
813         int loc_DeferredMod_Diffuse;
814         int loc_DeferredMod_Specular;
815         int loc_DistortScaleRefractReflect;
816         int loc_EyePosition;
817         int loc_FogColor;
818         int loc_FogHeightFade;
819         int loc_FogPlane;
820         int loc_FogPlaneViewDist;
821         int loc_FogRangeRecip;
822         int loc_LightColor;
823         int loc_LightDir;
824         int loc_LightPosition;
825         int loc_OffsetMapping_ScaleSteps;
826         int loc_OffsetMapping_LodDistance;
827         int loc_OffsetMapping_Bias;
828         int loc_PixelSize;
829         int loc_ReflectColor;
830         int loc_ReflectFactor;
831         int loc_ReflectOffset;
832         int loc_RefractColor;
833         int loc_Saturation;
834         int loc_ScreenCenterRefractReflect;
835         int loc_ScreenScaleRefractReflect;
836         int loc_ScreenToDepth;
837         int loc_ShadowMap_Parameters;
838         int loc_ShadowMap_TextureScale;
839         int loc_SpecularPower;
840         int loc_Skeletal_Transform12;
841         int loc_UserVec1;
842         int loc_UserVec2;
843         int loc_UserVec3;
844         int loc_UserVec4;
845         int loc_ViewTintColor;
846         int loc_ViewToLight;
847         int loc_ModelToLight;
848         int loc_TexMatrix;
849         int loc_BackgroundTexMatrix;
850         int loc_ModelViewProjectionMatrix;
851         int loc_ModelViewMatrix;
852         int loc_PixelToScreenTexCoord;
853         int loc_ModelToReflectCube;
854         int loc_ShadowMapMatrix;
855         int loc_BloomColorSubtract;
856         int loc_NormalmapScrollBlend;
857         int loc_BounceGridMatrix;
858         int loc_BounceGridIntensity;
859         /// uniform block bindings
860         int ubibind_Skeletal_Transform12_UniformBlock;
861         /// uniform block indices
862         int ubiloc_Skeletal_Transform12_UniformBlock;
863 }
864 r_glsl_permutation_t;
865
866 #define SHADERPERMUTATION_HASHSIZE 256
867
868
869 // non-degradable "lightweight" shader parameters to keep the permutations simpler
870 // these can NOT degrade! only use for simple stuff
871 enum
872 {
873         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
874         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
875         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
877         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
878         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
879         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
880         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
881         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
882         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
883         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
884         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
885         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
886         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
887 };
888 #define SHADERSTATICPARMS_COUNT 14
889
890 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
891 static int shaderstaticparms_count = 0;
892
893 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
894 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
895
896 extern qboolean r_shadow_shadowmapsampler;
897 extern int r_shadow_shadowmappcf;
898 qboolean R_CompileShader_CheckStaticParms(void)
899 {
900         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
901         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
902         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
903
904         // detect all
905         if (r_glsl_saturation_redcompensate.integer)
906                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
907         if (r_glsl_vertextextureblend_usebothalphas.integer)
908                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
909         if (r_shadow_glossexact.integer)
910                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
911         if (r_glsl_postprocess.integer)
912         {
913                 if (r_glsl_postprocess_uservec1_enable.integer)
914                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
915                 if (r_glsl_postprocess_uservec2_enable.integer)
916                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
917                 if (r_glsl_postprocess_uservec3_enable.integer)
918                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
919                 if (r_glsl_postprocess_uservec4_enable.integer)
920                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
921         }
922         if (r_fxaa.integer)
923                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
924         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
926
927         if (r_shadow_shadowmapsampler)
928                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
929         if (r_shadow_shadowmappcf > 1)
930                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
931         else if (r_shadow_shadowmappcf)
932                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
933         if (r_celshading.integer)
934                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
935         if (r_celoutlines.integer)
936                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
937
938         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
939 }
940
941 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
942         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
943                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
944         else \
945                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
946 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
947 {
948         shaderstaticparms_count = 0;
949
950         // emit all
951         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
952         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
953         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
954         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
955         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
956         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
957         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
958         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
959         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
960         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
961         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
962         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
963         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
964         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
965 }
966
967 /// information about each possible shader permutation
968 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
969 /// currently selected permutation
970 r_glsl_permutation_t *r_glsl_permutation;
971 /// storage for permutations linked in the hash table
972 memexpandablearray_t r_glsl_permutationarray;
973
974 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
975 {
976         //unsigned int hashdepth = 0;
977         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
978         r_glsl_permutation_t *p;
979         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
980         {
981                 if (p->mode == mode && p->permutation == permutation)
982                 {
983                         //if (hashdepth > 10)
984                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
985                         return p;
986                 }
987                 //hashdepth++;
988         }
989         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
990         p->mode = mode;
991         p->permutation = permutation;
992         p->hashnext = r_glsl_permutationhash[mode][hashindex];
993         r_glsl_permutationhash[mode][hashindex] = p;
994         //if (hashdepth > 10)
995         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
996         return p;
997 }
998
999 static char *R_ShaderStrCat(const char **strings)
1000 {
1001         char *string, *s;
1002         const char **p = strings;
1003         const char *t;
1004         size_t len = 0;
1005         for (p = strings;(t = *p);p++)
1006                 len += strlen(t);
1007         len++;
1008         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1009         len = 0;
1010         for (p = strings;(t = *p);p++)
1011         {
1012                 len = strlen(t);
1013                 memcpy(s, t, len);
1014                 s += len;
1015         }
1016         *s = 0;
1017         return string;
1018 }
1019
1020 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1021 {
1022         char *shaderstring;
1023         if (!filename || !filename[0])
1024                 return NULL;
1025         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1026         if (!strcmp(filename, "glsl/default.glsl"))
1027         {
1028                 if (builtinonly)
1029                         return R_ShaderStrCat(builtinshaderstrings);
1030                 if (!glslshaderstring)
1031                 {
1032                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1033                         if (glslshaderstring)
1034                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1035                         else
1036                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1037                 }
1038                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1039                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1040                 return shaderstring;
1041         }
1042         if (!strcmp(filename, "hlsl/default.hlsl"))
1043         {
1044                 if (builtinonly)
1045                         return R_ShaderStrCat(builtinhlslshaderstrings);
1046                 if (!hlslshaderstring)
1047                 {
1048                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1049                         if (hlslshaderstring)
1050                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1051                         else
1052                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1053                 }
1054                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1055                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1056                 return shaderstring;
1057         }
1058         // we don't have builtin strings for any other files
1059         if (builtinonly)
1060                 return NULL;
1061         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1062         if (shaderstring)
1063         {
1064                 if (printfromdisknotice)
1065                         Con_DPrintf("from disk %s... ", filename);
1066                 return shaderstring;
1067         }
1068         return shaderstring;
1069 }
1070
1071 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1072 {
1073         int i;
1074         int ubibind;
1075         int sampler;
1076         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1077         char *sourcestring;
1078         char permutationname[256];
1079         int vertstrings_count = 0;
1080         int geomstrings_count = 0;
1081         int fragstrings_count = 0;
1082         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1083         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1084         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1085
1086         if (p->compiled)
1087                 return;
1088         p->compiled = true;
1089         p->program = 0;
1090
1091         permutationname[0] = 0;
1092         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1093
1094         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1095
1096         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1097         if(vid.support.glshaderversion >= 140)
1098         {
1099                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1100                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1101                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1102                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1103                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1104                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1105         }
1106         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1107         else if(vid.support.glshaderversion >= 130)
1108         {
1109                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1110                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1111                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1112                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1113                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1114                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1115         }
1116
1117         // the first pretext is which type of shader to compile as
1118         // (later these will all be bound together as a program object)
1119         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1120         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1121         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1122
1123         // the second pretext is the mode (for example a light source)
1124         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1125         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1126         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1127         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1128
1129         // now add all the permutation pretexts
1130         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1131         {
1132                 if (permutation & (1<<i))
1133                 {
1134                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1135                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1136                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1137                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1138                 }
1139                 else
1140                 {
1141                         // keep line numbers correct
1142                         vertstrings_list[vertstrings_count++] = "\n";
1143                         geomstrings_list[geomstrings_count++] = "\n";
1144                         fragstrings_list[fragstrings_count++] = "\n";
1145                 }
1146         }
1147
1148         // add static parms
1149         R_CompileShader_AddStaticParms(mode, permutation);
1150         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1151         vertstrings_count += shaderstaticparms_count;
1152         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1153         geomstrings_count += shaderstaticparms_count;
1154         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1155         fragstrings_count += shaderstaticparms_count;
1156
1157         // now append the shader text itself
1158         vertstrings_list[vertstrings_count++] = sourcestring;
1159         geomstrings_list[geomstrings_count++] = sourcestring;
1160         fragstrings_list[fragstrings_count++] = sourcestring;
1161
1162         // compile the shader program
1163         if (vertstrings_count + geomstrings_count + fragstrings_count)
1164                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1165         if (p->program)
1166         {
1167                 CHECKGLERROR
1168                 qglUseProgram(p->program);CHECKGLERROR
1169                 // look up all the uniform variable names we care about, so we don't
1170                 // have to look them up every time we set them
1171
1172 #if 0
1173                 // debugging aid
1174                 {
1175                         GLint activeuniformindex = 0;
1176                         GLint numactiveuniforms = 0;
1177                         char uniformname[128];
1178                         GLsizei uniformnamelength = 0;
1179                         GLint uniformsize = 0;
1180                         GLenum uniformtype = 0;
1181                         memset(uniformname, 0, sizeof(uniformname));
1182                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1183                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1184                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1185                         {
1186                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1187                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1188                         }
1189                 }
1190 #endif
1191
1192                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1193                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1194                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1195                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1196                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1197                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1198                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1199                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1200                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1201                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1202                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1203                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1204                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1205                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1206                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1207                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1208                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1209                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1210                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1211                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1212                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1213                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1214                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1215                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1216                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1217                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1218                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1219                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1220                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1221                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1222                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1223                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1224                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1225                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1226                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1227                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1228                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1229                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1230                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1231                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1232                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1233                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1234                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1235                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1236                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1237                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1238                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1239                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1240                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1241                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1242                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1243                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1244                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1245                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1246                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1247                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1248                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1249                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1250                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1251                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1252                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1253                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1254                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1255                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1256                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1257                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1258                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1259                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1260                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1261                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1262                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1263                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1264                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1265                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1266                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1267                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1268                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1269                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1270                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1271                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1272                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1273                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1274                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1275                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1276                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1277                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1278                 // initialize the samplers to refer to the texture units we use
1279                 p->tex_Texture_First = -1;
1280                 p->tex_Texture_Second = -1;
1281                 p->tex_Texture_GammaRamps = -1;
1282                 p->tex_Texture_Normal = -1;
1283                 p->tex_Texture_Color = -1;
1284                 p->tex_Texture_Gloss = -1;
1285                 p->tex_Texture_Glow = -1;
1286                 p->tex_Texture_SecondaryNormal = -1;
1287                 p->tex_Texture_SecondaryColor = -1;
1288                 p->tex_Texture_SecondaryGloss = -1;
1289                 p->tex_Texture_SecondaryGlow = -1;
1290                 p->tex_Texture_Pants = -1;
1291                 p->tex_Texture_Shirt = -1;
1292                 p->tex_Texture_FogHeightTexture = -1;
1293                 p->tex_Texture_FogMask = -1;
1294                 p->tex_Texture_Lightmap = -1;
1295                 p->tex_Texture_Deluxemap = -1;
1296                 p->tex_Texture_Attenuation = -1;
1297                 p->tex_Texture_Cube = -1;
1298                 p->tex_Texture_Refraction = -1;
1299                 p->tex_Texture_Reflection = -1;
1300                 p->tex_Texture_ShadowMap2D = -1;
1301                 p->tex_Texture_CubeProjection = -1;
1302                 p->tex_Texture_ScreenNormalMap = -1;
1303                 p->tex_Texture_ScreenDiffuse = -1;
1304                 p->tex_Texture_ScreenSpecular = -1;
1305                 p->tex_Texture_ReflectMask = -1;
1306                 p->tex_Texture_ReflectCube = -1;
1307                 p->tex_Texture_BounceGrid = -1;
1308                 // bind the texture samplers in use
1309                 sampler = 0;
1310                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1311                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1312                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1313                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1314                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1315                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1316                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1317                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1318                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1319                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1320                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1321                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1322                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1323                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1324                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1325                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1326                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1327                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1328                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1329                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1330                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1331                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1332                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1333                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1334                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1335                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1336                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1337                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1338                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1339                 // get the uniform block indices so we can bind them
1340 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1341                 if (vid.support.arb_uniform_buffer_object)
1342                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1343                 else
1344 #endif
1345                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1346                 // clear the uniform block bindings
1347                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1348                 // bind the uniform blocks in use
1349                 ubibind = 0;
1350 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1351                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1352 #endif
1353                 // we're done compiling and setting up the shader, at least until it is used
1354                 CHECKGLERROR
1355                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1356         }
1357         else
1358                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1359
1360         // free the strings
1361         if (sourcestring)
1362                 Mem_Free(sourcestring);
1363 }
1364
1365 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1366 {
1367         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1368         if (r_glsl_permutation != perm)
1369         {
1370                 r_glsl_permutation = perm;
1371                 if (!r_glsl_permutation->program)
1372                 {
1373                         if (!r_glsl_permutation->compiled)
1374                         {
1375                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1376                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1377                         }
1378                         if (!r_glsl_permutation->program)
1379                         {
1380                                 // remove features until we find a valid permutation
1381                                 int i;
1382                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1383                                 {
1384                                         // reduce i more quickly whenever it would not remove any bits
1385                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1386                                         if (!(permutation & j))
1387                                                 continue;
1388                                         permutation -= j;
1389                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1390                                         if (!r_glsl_permutation->compiled)
1391                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1392                                         if (r_glsl_permutation->program)
1393                                                 break;
1394                                 }
1395                                 if (i >= SHADERPERMUTATION_COUNT)
1396                                 {
1397                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1398                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1399                                         qglUseProgram(0);CHECKGLERROR
1400                                         return; // no bit left to clear, entire mode is broken
1401                                 }
1402                         }
1403                 }
1404                 CHECKGLERROR
1405                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1406         }
1407         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1408         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1409         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1410         CHECKGLERROR
1411 }
1412
1413 #ifdef SUPPORTD3D
1414
1415 #ifdef SUPPORTD3D
1416 #include <d3d9.h>
1417 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1418 extern D3DCAPS9 vid_d3d9caps;
1419 #endif
1420
1421 struct r_hlsl_permutation_s;
1422 typedef struct r_hlsl_permutation_s
1423 {
1424         /// hash lookup data
1425         struct r_hlsl_permutation_s *hashnext;
1426         unsigned int mode;
1427         unsigned int permutation;
1428
1429         /// indicates if we have tried compiling this permutation already
1430         qboolean compiled;
1431         /// NULL if compilation failed
1432         IDirect3DVertexShader9 *vertexshader;
1433         IDirect3DPixelShader9 *pixelshader;
1434 }
1435 r_hlsl_permutation_t;
1436
1437 typedef enum D3DVSREGISTER_e
1438 {
1439         D3DVSREGISTER_TexMatrix = 0, // float4x4
1440         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1441         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1442         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1443         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1444         D3DVSREGISTER_ModelToLight = 20, // float4x4
1445         D3DVSREGISTER_EyePosition = 24,
1446         D3DVSREGISTER_FogPlane = 25,
1447         D3DVSREGISTER_LightDir = 26,
1448         D3DVSREGISTER_LightPosition = 27,
1449 }
1450 D3DVSREGISTER_t;
1451
1452 typedef enum D3DPSREGISTER_e
1453 {
1454         D3DPSREGISTER_Alpha = 0,
1455         D3DPSREGISTER_BloomBlur_Parameters = 1,
1456         D3DPSREGISTER_ClientTime = 2,
1457         D3DPSREGISTER_Color_Ambient = 3,
1458         D3DPSREGISTER_Color_Diffuse = 4,
1459         D3DPSREGISTER_Color_Specular = 5,
1460         D3DPSREGISTER_Color_Glow = 6,
1461         D3DPSREGISTER_Color_Pants = 7,
1462         D3DPSREGISTER_Color_Shirt = 8,
1463         D3DPSREGISTER_DeferredColor_Ambient = 9,
1464         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1465         D3DPSREGISTER_DeferredColor_Specular = 11,
1466         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1467         D3DPSREGISTER_DeferredMod_Specular = 13,
1468         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1469         D3DPSREGISTER_EyePosition = 15, // unused
1470         D3DPSREGISTER_FogColor = 16,
1471         D3DPSREGISTER_FogHeightFade = 17,
1472         D3DPSREGISTER_FogPlane = 18,
1473         D3DPSREGISTER_FogPlaneViewDist = 19,
1474         D3DPSREGISTER_FogRangeRecip = 20,
1475         D3DPSREGISTER_LightColor = 21,
1476         D3DPSREGISTER_LightDir = 22, // unused
1477         D3DPSREGISTER_LightPosition = 23,
1478         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1479         D3DPSREGISTER_PixelSize = 25,
1480         D3DPSREGISTER_ReflectColor = 26,
1481         D3DPSREGISTER_ReflectFactor = 27,
1482         D3DPSREGISTER_ReflectOffset = 28,
1483         D3DPSREGISTER_RefractColor = 29,
1484         D3DPSREGISTER_Saturation = 30,
1485         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1486         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1487         D3DPSREGISTER_ScreenToDepth = 33,
1488         D3DPSREGISTER_ShadowMap_Parameters = 34,
1489         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1490         D3DPSREGISTER_SpecularPower = 36,
1491         D3DPSREGISTER_UserVec1 = 37,
1492         D3DPSREGISTER_UserVec2 = 38,
1493         D3DPSREGISTER_UserVec3 = 39,
1494         D3DPSREGISTER_UserVec4 = 40,
1495         D3DPSREGISTER_ViewTintColor = 41,
1496         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1497         D3DPSREGISTER_BloomColorSubtract = 43,
1498         D3DPSREGISTER_ViewToLight = 44, // float4x4
1499         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1500         D3DPSREGISTER_NormalmapScrollBlend = 52,
1501         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1502         D3DPSREGISTER_OffsetMapping_Bias = 54,
1503         // next at 54
1504 }
1505 D3DPSREGISTER_t;
1506
1507 /// information about each possible shader permutation
1508 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1509 /// currently selected permutation
1510 r_hlsl_permutation_t *r_hlsl_permutation;
1511 /// storage for permutations linked in the hash table
1512 memexpandablearray_t r_hlsl_permutationarray;
1513
1514 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1515 {
1516         //unsigned int hashdepth = 0;
1517         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1518         r_hlsl_permutation_t *p;
1519         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1520         {
1521                 if (p->mode == mode && p->permutation == permutation)
1522                 {
1523                         //if (hashdepth > 10)
1524                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1525                         return p;
1526                 }
1527                 //hashdepth++;
1528         }
1529         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1530         p->mode = mode;
1531         p->permutation = permutation;
1532         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1533         r_hlsl_permutationhash[mode][hashindex] = p;
1534         //if (hashdepth > 10)
1535         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1536         return p;
1537 }
1538
1539 #include <d3dx9.h>
1540 //#include <d3dx9shader.h>
1541 //#include <d3dx9mesh.h>
1542
1543 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1544 {
1545         DWORD *vsbin = NULL;
1546         DWORD *psbin = NULL;
1547         fs_offset_t vsbinsize;
1548         fs_offset_t psbinsize;
1549 //      IDirect3DVertexShader9 *vs = NULL;
1550 //      IDirect3DPixelShader9 *ps = NULL;
1551         ID3DXBuffer *vslog = NULL;
1552         ID3DXBuffer *vsbuffer = NULL;
1553         ID3DXConstantTable *vsconstanttable = NULL;
1554         ID3DXBuffer *pslog = NULL;
1555         ID3DXBuffer *psbuffer = NULL;
1556         ID3DXConstantTable *psconstanttable = NULL;
1557         int vsresult = 0;
1558         int psresult = 0;
1559         char temp[MAX_INPUTLINE];
1560         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1561         char vabuf[1024];
1562         qboolean debugshader = gl_paranoid.integer != 0;
1563         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1564         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1565         if (!debugshader)
1566         {
1567                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1568                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1569         }
1570         if ((!vsbin && vertstring) || (!psbin && fragstring))
1571         {
1572                 const char* dllnames_d3dx9 [] =
1573                 {
1574                         "d3dx9_43.dll",
1575                         "d3dx9_42.dll",
1576                         "d3dx9_41.dll",
1577                         "d3dx9_40.dll",
1578                         "d3dx9_39.dll",
1579                         "d3dx9_38.dll",
1580                         "d3dx9_37.dll",
1581                         "d3dx9_36.dll",
1582                         "d3dx9_35.dll",
1583                         "d3dx9_34.dll",
1584                         "d3dx9_33.dll",
1585                         "d3dx9_32.dll",
1586                         "d3dx9_31.dll",
1587                         "d3dx9_30.dll",
1588                         "d3dx9_29.dll",
1589                         "d3dx9_28.dll",
1590                         "d3dx9_27.dll",
1591                         "d3dx9_26.dll",
1592                         "d3dx9_25.dll",
1593                         "d3dx9_24.dll",
1594                         NULL
1595                 };
1596                 dllhandle_t d3dx9_dll = NULL;
1597                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1598                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1599                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1600                 dllfunction_t d3dx9_dllfuncs[] =
1601                 {
1602                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1603                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1604                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1605                         {NULL, NULL}
1606                 };
1607                 // 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...
1608 #ifndef ID3DXBuffer_GetBufferPointer
1609 #if !defined(__cplusplus) || defined(CINTERFACE)
1610 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1611 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1612 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1613 #else
1614 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1615 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1616 #define ID3DXBuffer_Release(p)            (p)->Release()
1617 #endif
1618 #endif
1619                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1620                 {
1621                         DWORD shaderflags = 0;
1622                         if (debugshader)
1623                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1624                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1625                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1626                         if (vertstring && vertstring[0])
1627                         {
1628                                 if (debugshader)
1629                                 {
1630                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1631                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1632                                 }
1633                                 else
1634                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1635                                 if (vsbuffer)
1636                                 {
1637                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1638                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1639                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1640                                         ID3DXBuffer_Release(vsbuffer);
1641                                 }
1642                                 if (vslog)
1643                                 {
1644                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1645                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1646                                         ID3DXBuffer_Release(vslog);
1647                                 }
1648                         }
1649                         if (fragstring && fragstring[0])
1650                         {
1651                                 if (debugshader)
1652                                 {
1653                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1654                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1655                                 }
1656                                 else
1657                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1658                                 if (psbuffer)
1659                                 {
1660                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1661                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1662                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1663                                         ID3DXBuffer_Release(psbuffer);
1664                                 }
1665                                 if (pslog)
1666                                 {
1667                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1668                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1669                                         ID3DXBuffer_Release(pslog);
1670                                 }
1671                         }
1672                         Sys_UnloadLibrary(&d3dx9_dll);
1673                 }
1674                 else
1675                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1676         }
1677         if (vsbin && psbin)
1678         {
1679                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1680                 if (FAILED(vsresult))
1681                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1682                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1683                 if (FAILED(psresult))
1684                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1685         }
1686         // free the shader data
1687         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1688         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1689 }
1690
1691 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1692 {
1693         int i;
1694         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1695         int vertstring_length = 0;
1696         int geomstring_length = 0;
1697         int fragstring_length = 0;
1698         char *t;
1699         char *sourcestring;
1700         char *vertstring, *geomstring, *fragstring;
1701         char permutationname[256];
1702         char cachename[256];
1703         int vertstrings_count = 0;
1704         int geomstrings_count = 0;
1705         int fragstrings_count = 0;
1706         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1707         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1708         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1709
1710         if (p->compiled)
1711                 return;
1712         p->compiled = true;
1713         p->vertexshader = NULL;
1714         p->pixelshader = NULL;
1715
1716         permutationname[0] = 0;
1717         cachename[0] = 0;
1718         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1719
1720         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1721         strlcat(cachename, "hlsl/", sizeof(cachename));
1722
1723         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1724         vertstrings_count = 0;
1725         geomstrings_count = 0;
1726         fragstrings_count = 0;
1727         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1728         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1729         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1730
1731         // the first pretext is which type of shader to compile as
1732         // (later these will all be bound together as a program object)
1733         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1734         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1735         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1736
1737         // the second pretext is the mode (for example a light source)
1738         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1739         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1740         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1741         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1742         strlcat(cachename, modeinfo->name, sizeof(cachename));
1743
1744         // now add all the permutation pretexts
1745         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1746         {
1747                 if (permutation & (1<<i))
1748                 {
1749                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1750                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1751                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1752                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1753                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1754                 }
1755                 else
1756                 {
1757                         // keep line numbers correct
1758                         vertstrings_list[vertstrings_count++] = "\n";
1759                         geomstrings_list[geomstrings_count++] = "\n";
1760                         fragstrings_list[fragstrings_count++] = "\n";
1761                 }
1762         }
1763
1764         // add static parms
1765         R_CompileShader_AddStaticParms(mode, permutation);
1766         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1767         vertstrings_count += shaderstaticparms_count;
1768         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1769         geomstrings_count += shaderstaticparms_count;
1770         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1771         fragstrings_count += shaderstaticparms_count;
1772
1773         // replace spaces in the cachename with _ characters
1774         for (i = 0;cachename[i];i++)
1775                 if (cachename[i] == ' ')
1776                         cachename[i] = '_';
1777
1778         // now append the shader text itself
1779         vertstrings_list[vertstrings_count++] = sourcestring;
1780         geomstrings_list[geomstrings_count++] = sourcestring;
1781         fragstrings_list[fragstrings_count++] = sourcestring;
1782
1783         vertstring_length = 0;
1784         for (i = 0;i < vertstrings_count;i++)
1785                 vertstring_length += (int)strlen(vertstrings_list[i]);
1786         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1787         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1788                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1789
1790         geomstring_length = 0;
1791         for (i = 0;i < geomstrings_count;i++)
1792                 geomstring_length += (int)strlen(geomstrings_list[i]);
1793         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1794         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1795                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1796
1797         fragstring_length = 0;
1798         for (i = 0;i < fragstrings_count;i++)
1799                 fragstring_length += (int)strlen(fragstrings_list[i]);
1800         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1801         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1802                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1803
1804         // try to load the cached shader, or generate one
1805         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1806
1807         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1808                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1809         else
1810                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1811
1812         // free the strings
1813         if (vertstring)
1814                 Mem_Free(vertstring);
1815         if (geomstring)
1816                 Mem_Free(geomstring);
1817         if (fragstring)
1818                 Mem_Free(fragstring);
1819         if (sourcestring)
1820                 Mem_Free(sourcestring);
1821 }
1822
1823 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1824 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1825 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);}
1826 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);}
1827 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);}
1828 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);}
1829
1830 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1831 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1832 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);}
1833 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);}
1834 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);}
1835 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);}
1836
1837 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1838 {
1839         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1840         if (r_hlsl_permutation != perm)
1841         {
1842                 r_hlsl_permutation = perm;
1843                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1844                 {
1845                         if (!r_hlsl_permutation->compiled)
1846                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1847                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1848                         {
1849                                 // remove features until we find a valid permutation
1850                                 int i;
1851                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1852                                 {
1853                                         // reduce i more quickly whenever it would not remove any bits
1854                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1855                                         if (!(permutation & j))
1856                                                 continue;
1857                                         permutation -= j;
1858                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1859                                         if (!r_hlsl_permutation->compiled)
1860                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1861                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1862                                                 break;
1863                                 }
1864                                 if (i >= SHADERPERMUTATION_COUNT)
1865                                 {
1866                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1867                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1868                                         return; // no bit left to clear, entire mode is broken
1869                                 }
1870                         }
1871                 }
1872                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1873                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1874         }
1875         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1876         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1877         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1878 }
1879 #endif
1880
1881 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1882 {
1883         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1884         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1885         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1886         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1887 }
1888
1889 void R_GLSL_Restart_f(void)
1890 {
1891         unsigned int i, limit;
1892         if (glslshaderstring)
1893                 Mem_Free(glslshaderstring);
1894         glslshaderstring = NULL;
1895         if (hlslshaderstring)
1896                 Mem_Free(hlslshaderstring);
1897         hlslshaderstring = NULL;
1898         switch(vid.renderpath)
1899         {
1900         case RENDERPATH_D3D9:
1901 #ifdef SUPPORTD3D
1902                 {
1903                         r_hlsl_permutation_t *p;
1904                         r_hlsl_permutation = NULL;
1905                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1906                         for (i = 0;i < limit;i++)
1907                         {
1908                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1909                                 {
1910                                         if (p->vertexshader)
1911                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1912                                         if (p->pixelshader)
1913                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1914                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1915                                 }
1916                         }
1917                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1918                 }
1919 #endif
1920                 break;
1921         case RENDERPATH_D3D10:
1922                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1923                 break;
1924         case RENDERPATH_D3D11:
1925                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1926                 break;
1927         case RENDERPATH_GL20:
1928         case RENDERPATH_GLES2:
1929                 {
1930                         r_glsl_permutation_t *p;
1931                         r_glsl_permutation = NULL;
1932                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1933                         for (i = 0;i < limit;i++)
1934                         {
1935                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1936                                 {
1937                                         GL_Backend_FreeProgram(p->program);
1938                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1939                                 }
1940                         }
1941                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1942                 }
1943                 break;
1944         case RENDERPATH_GL11:
1945         case RENDERPATH_GL13:
1946         case RENDERPATH_GLES1:
1947                 break;
1948         case RENDERPATH_SOFT:
1949                 break;
1950         }
1951 }
1952
1953 static void R_GLSL_DumpShader_f(void)
1954 {
1955         int i, language, mode, dupe;
1956         char *text;
1957         shadermodeinfo_t *modeinfo;
1958         qfile_t *file;
1959
1960         for (language = 0;language < 2;language++)
1961         {
1962                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1963                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1964                 {
1965                         // don't dump the same file multiple times (most or all shaders come from the same file)
1966                         for (dupe = mode - 1;dupe >= 0;dupe--)
1967                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1968                                         break;
1969                         if (dupe >= 0)
1970                                 continue;
1971                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1972                         if (!text)
1973                                 continue;
1974                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1975                         if (file)
1976                         {
1977                                 FS_Print(file, "/* The engine may define the following macros:\n");
1978                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1979                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1980                                         FS_Print(file, modeinfo[i].pretext);
1981                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1982                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1983                                 FS_Print(file, "*/\n");
1984                                 FS_Print(file, text);
1985                                 FS_Close(file);
1986                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1987                         }
1988                         else
1989                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1990                         Mem_Free(text);
1991                 }
1992         }
1993 }
1994
1995 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1996 {
1997         unsigned int permutation = 0;
1998         if (r_trippy.integer && !notrippy)
1999                 permutation |= SHADERPERMUTATION_TRIPPY;
2000         permutation |= SHADERPERMUTATION_VIEWTINT;
2001         if (first)
2002                 permutation |= SHADERPERMUTATION_DIFFUSE;
2003         if (second)
2004                 permutation |= SHADERPERMUTATION_SPECULAR;
2005         if (texturemode == GL_MODULATE)
2006                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2007         else if (texturemode == GL_ADD)
2008                 permutation |= SHADERPERMUTATION_GLOW;
2009         else if (texturemode == GL_DECAL)
2010                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2011         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2012                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2013         if (suppresstexalpha)
2014                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2015         if (!second)
2016                 texturemode = GL_MODULATE;
2017         if (vid.allowalphatocoverage)
2018                 GL_AlphaToCoverage(false);
2019         switch (vid.renderpath)
2020         {
2021         case RENDERPATH_D3D9:
2022 #ifdef SUPPORTD3D
2023                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2024                 R_Mesh_TexBind(GL20TU_FIRST , first );
2025                 R_Mesh_TexBind(GL20TU_SECOND, second);
2026                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2027                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2028 #endif
2029                 break;
2030         case RENDERPATH_D3D10:
2031                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2032                 break;
2033         case RENDERPATH_D3D11:
2034                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2035                 break;
2036         case RENDERPATH_GL20:
2037         case RENDERPATH_GLES2:
2038                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2039                 if (r_glsl_permutation->tex_Texture_First >= 0)
2040                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2041                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2042                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2043                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2044                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2045                 break;
2046         case RENDERPATH_GL13:
2047         case RENDERPATH_GLES1:
2048                 R_Mesh_TexBind(0, first );
2049                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2050                 R_Mesh_TexMatrix(0, NULL);
2051                 R_Mesh_TexBind(1, second);
2052                 if (second)
2053                 {
2054                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2055                         R_Mesh_TexMatrix(1, NULL);
2056                 }
2057                 break;
2058         case RENDERPATH_GL11:
2059                 R_Mesh_TexBind(0, first );
2060                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2061                 R_Mesh_TexMatrix(0, NULL);
2062                 break;
2063         case RENDERPATH_SOFT:
2064                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2065                 R_Mesh_TexBind(GL20TU_FIRST , first );
2066                 R_Mesh_TexBind(GL20TU_SECOND, second);
2067                 break;
2068         }
2069 }
2070
2071 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2072 {
2073         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2074 }
2075
2076 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2077 {
2078         unsigned int permutation = 0;
2079         if (r_trippy.integer && !notrippy)
2080                 permutation |= SHADERPERMUTATION_TRIPPY;
2081         if (depthrgb)
2082                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2083         if (skeletal)
2084                 permutation |= SHADERPERMUTATION_SKELETAL;
2085
2086         if (vid.allowalphatocoverage)
2087                 GL_AlphaToCoverage(false);
2088         switch (vid.renderpath)
2089         {
2090         case RENDERPATH_D3D9:
2091 #ifdef SUPPORTD3D
2092                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2093 #endif
2094                 break;
2095         case RENDERPATH_D3D10:
2096                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2097                 break;
2098         case RENDERPATH_D3D11:
2099                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2100                 break;
2101         case RENDERPATH_GL20:
2102         case RENDERPATH_GLES2:
2103                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2104 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2105                 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);
2106 #endif
2107                 break;
2108         case RENDERPATH_GL13:
2109         case RENDERPATH_GLES1:
2110                 R_Mesh_TexBind(0, 0);
2111                 R_Mesh_TexBind(1, 0);
2112                 break;
2113         case RENDERPATH_GL11:
2114                 R_Mesh_TexBind(0, 0);
2115                 break;
2116         case RENDERPATH_SOFT:
2117                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2118                 break;
2119         }
2120 }
2121
2122 extern qboolean r_shadow_usingdeferredprepass;
2123 extern rtexture_t *r_shadow_attenuationgradienttexture;
2124 extern rtexture_t *r_shadow_attenuation2dtexture;
2125 extern rtexture_t *r_shadow_attenuation3dtexture;
2126 extern qboolean r_shadow_usingshadowmap2d;
2127 extern qboolean r_shadow_usingshadowmaportho;
2128 extern float r_shadow_shadowmap_texturescale[2];
2129 extern float r_shadow_shadowmap_parameters[4];
2130 extern qboolean r_shadow_shadowmapvsdct;
2131 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2132 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2133 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2134 extern matrix4x4_t r_shadow_shadowmapmatrix;
2135 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2136 extern int r_shadow_prepass_width;
2137 extern int r_shadow_prepass_height;
2138 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2139 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2140 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2141 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2142
2143 #define BLENDFUNC_ALLOWS_COLORMOD      1
2144 #define BLENDFUNC_ALLOWS_FOG           2
2145 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2146 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2147 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2148 static int R_BlendFuncFlags(int src, int dst)
2149 {
2150         int r = 0;
2151
2152         // a blendfunc allows colormod if:
2153         // a) it can never keep the destination pixel invariant, or
2154         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2155         // this is to prevent unintended side effects from colormod
2156
2157         // a blendfunc allows fog if:
2158         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2159         // this is to prevent unintended side effects from fog
2160
2161         // these checks are the output of fogeval.pl
2162
2163         r |= BLENDFUNC_ALLOWS_COLORMOD;
2164         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2165         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2166         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2167         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2168         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2169         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2170         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2171         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2172         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2173         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2174         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2175         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2176         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2177         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2178         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2179         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2181         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2182         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2183         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2184         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2185
2186         return r;
2187 }
2188
2189 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2190 {
2191         // select a permutation of the lighting shader appropriate to this
2192         // combination of texture, entity, light source, and fogging, only use the
2193         // minimum features necessary to avoid wasting rendering time in the
2194         // fragment shader on features that are not being used
2195         unsigned int permutation = 0;
2196         unsigned int mode = 0;
2197         int blendfuncflags;
2198         static float dummy_colormod[3] = {1, 1, 1};
2199         float *colormod = rsurface.colormod;
2200         float m16f[16];
2201         matrix4x4_t tempmatrix;
2202         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2203         if (r_trippy.integer && !notrippy)
2204                 permutation |= SHADERPERMUTATION_TRIPPY;
2205         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2206                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2207         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2208                 permutation |= SHADERPERMUTATION_OCCLUDE;
2209         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2210                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2211         if (rsurfacepass == RSURFPASS_BACKGROUND)
2212         {
2213                 // distorted background
2214                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2215                 {
2216                         mode = SHADERMODE_WATER;
2217                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2218                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2219                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2220                         {
2221                                 // this is the right thing to do for wateralpha
2222                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2223                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2224                         }
2225                         else
2226                         {
2227                                 // this is the right thing to do for entity alpha
2228                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2229                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2230                         }
2231                 }
2232                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2233                 {
2234                         mode = SHADERMODE_REFRACTION;
2235                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2236                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2237                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2238                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2239                 }
2240                 else
2241                 {
2242                         mode = SHADERMODE_GENERIC;
2243                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2244                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2245                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2246                 }
2247                 if (vid.allowalphatocoverage)
2248                         GL_AlphaToCoverage(false);
2249         }
2250         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2251         {
2252                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2253                 {
2254                         switch(rsurface.texture->offsetmapping)
2255                         {
2256                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2257                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2258                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2259                         case OFFSETMAPPING_OFF: break;
2260                         }
2261                 }
2262                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2263                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2264                 // normalmap (deferred prepass), may use alpha test on diffuse
2265                 mode = SHADERMODE_DEFERREDGEOMETRY;
2266                 GL_BlendFunc(GL_ONE, GL_ZERO);
2267                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2268                 if (vid.allowalphatocoverage)
2269                         GL_AlphaToCoverage(false);
2270         }
2271         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2272         {
2273                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2274                 {
2275                         switch(rsurface.texture->offsetmapping)
2276                         {
2277                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2278                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2279                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2280                         case OFFSETMAPPING_OFF: break;
2281                         }
2282                 }
2283                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2284                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2285                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2286                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2287                 // light source
2288                 mode = SHADERMODE_LIGHTSOURCE;
2289                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2290                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2291                 if (diffusescale > 0)
2292                         permutation |= SHADERPERMUTATION_DIFFUSE;
2293                 if (specularscale > 0)
2294                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2295                 if (r_refdef.fogenabled)
2296                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2297                 if (rsurface.texture->colormapping)
2298                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2299                 if (r_shadow_usingshadowmap2d)
2300                 {
2301                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2302                         if(r_shadow_shadowmapvsdct)
2303                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2304
2305                         if (r_shadow_shadowmap2ddepthbuffer)
2306                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2307                 }
2308                 if (rsurface.texture->reflectmasktexture)
2309                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2310                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2311                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2312                 if (vid.allowalphatocoverage)
2313                         GL_AlphaToCoverage(false);
2314         }
2315         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2316         {
2317                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2318                 {
2319                         switch(rsurface.texture->offsetmapping)
2320                         {
2321                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2322                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2323                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2324                         case OFFSETMAPPING_OFF: break;
2325                         }
2326                 }
2327                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2328                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2329                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2330                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2331                 // unshaded geometry (fullbright or ambient model lighting)
2332                 mode = SHADERMODE_FLATCOLOR;
2333                 ambientscale = diffusescale = specularscale = 0;
2334                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2335                         permutation |= SHADERPERMUTATION_GLOW;
2336                 if (r_refdef.fogenabled)
2337                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2338                 if (rsurface.texture->colormapping)
2339                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2340                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2341                 {
2342                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2343                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2344
2345                         if (r_shadow_shadowmap2ddepthbuffer)
2346                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2347                 }
2348                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2349                         permutation |= SHADERPERMUTATION_REFLECTION;
2350                 if (rsurface.texture->reflectmasktexture)
2351                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2352                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2354                 // when using alphatocoverage, we don't need alphakill
2355                 if (vid.allowalphatocoverage)
2356                 {
2357                         if (r_transparent_alphatocoverage.integer)
2358                         {
2359                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2360                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2361                         }
2362                         else
2363                                 GL_AlphaToCoverage(false);
2364                 }
2365         }
2366         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2367         {
2368                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2369                 {
2370                         switch(rsurface.texture->offsetmapping)
2371                         {
2372                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2373                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2374                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2375                         case OFFSETMAPPING_OFF: break;
2376                         }
2377                 }
2378                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2379                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2380                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2381                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2382                 // directional model lighting
2383                 mode = SHADERMODE_LIGHTDIRECTION;
2384                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2385                         permutation |= SHADERPERMUTATION_GLOW;
2386                 permutation |= SHADERPERMUTATION_DIFFUSE;
2387                 if (specularscale > 0)
2388                         permutation |= SHADERPERMUTATION_SPECULAR;
2389                 if (r_refdef.fogenabled)
2390                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2391                 if (rsurface.texture->colormapping)
2392                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2393                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2394                 {
2395                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2396                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2397
2398                         if (r_shadow_shadowmap2ddepthbuffer)
2399                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2400                 }
2401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2402                         permutation |= SHADERPERMUTATION_REFLECTION;
2403                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2404                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2405                 if (rsurface.texture->reflectmasktexture)
2406                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2407                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2408                 {
2409                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2410                         if (r_shadow_bouncegriddirectional)
2411                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2412                 }
2413                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415                 // when using alphatocoverage, we don't need alphakill
2416                 if (vid.allowalphatocoverage)
2417                 {
2418                         if (r_transparent_alphatocoverage.integer)
2419                         {
2420                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2421                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2422                         }
2423                         else
2424                                 GL_AlphaToCoverage(false);
2425                 }
2426         }
2427         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2428         {
2429                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2430                 {
2431                         switch(rsurface.texture->offsetmapping)
2432                         {
2433                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2434                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2435                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2436                         case OFFSETMAPPING_OFF: break;
2437                         }
2438                 }
2439                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2440                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2442                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2443                 // ambient model lighting
2444                 mode = SHADERMODE_LIGHTDIRECTION;
2445                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2446                         permutation |= SHADERPERMUTATION_GLOW;
2447                 if (r_refdef.fogenabled)
2448                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2449                 if (rsurface.texture->colormapping)
2450                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2451                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2452                 {
2453                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2454                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2455
2456                         if (r_shadow_shadowmap2ddepthbuffer)
2457                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2458                 }
2459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2460                         permutation |= SHADERPERMUTATION_REFLECTION;
2461                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2462                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2463                 if (rsurface.texture->reflectmasktexture)
2464                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2465                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2466                 {
2467                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2468                         if (r_shadow_bouncegriddirectional)
2469                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2470                 }
2471                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2472                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2473                 // when using alphatocoverage, we don't need alphakill
2474                 if (vid.allowalphatocoverage)
2475                 {
2476                         if (r_transparent_alphatocoverage.integer)
2477                         {
2478                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2479                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2480                         }
2481                         else
2482                                 GL_AlphaToCoverage(false);
2483                 }
2484         }
2485         else
2486         {
2487                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2488                 {
2489                         switch(rsurface.texture->offsetmapping)
2490                         {
2491                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2492                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2493                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2494                         case OFFSETMAPPING_OFF: break;
2495                         }
2496                 }
2497                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2498                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2499                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2500                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2501                 // lightmapped wall
2502                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2503                         permutation |= SHADERPERMUTATION_GLOW;
2504                 if (r_refdef.fogenabled)
2505                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2506                 if (rsurface.texture->colormapping)
2507                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2508                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2509                 {
2510                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2511                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2512
2513                         if (r_shadow_shadowmap2ddepthbuffer)
2514                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2515                 }
2516                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2517                         permutation |= SHADERPERMUTATION_REFLECTION;
2518                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2519                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2520                 if (rsurface.texture->reflectmasktexture)
2521                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2522                 if (FAKELIGHT_ENABLED)
2523                 {
2524                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2525                         mode = SHADERMODE_FAKELIGHT;
2526                         permutation |= SHADERPERMUTATION_DIFFUSE;
2527                         if (specularscale > 0)
2528                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2529                 }
2530                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2531                 {
2532                         // deluxemapping (light direction texture)
2533                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2534                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2535                         else
2536                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2537                         permutation |= SHADERPERMUTATION_DIFFUSE;
2538                         if (specularscale > 0)
2539                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2540                 }
2541                 else if (r_glsl_deluxemapping.integer >= 2)
2542                 {
2543                         // fake deluxemapping (uniform light direction in tangentspace)
2544                         if (rsurface.uselightmaptexture)
2545                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2546                         else
2547                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2548                         permutation |= SHADERPERMUTATION_DIFFUSE;
2549                         if (specularscale > 0)
2550                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2551                 }
2552                 else if (rsurface.uselightmaptexture)
2553                 {
2554                         // ordinary lightmapping (q1bsp, q3bsp)
2555                         mode = SHADERMODE_LIGHTMAP;
2556                 }
2557                 else
2558                 {
2559                         // ordinary vertex coloring (q3bsp)
2560                         mode = SHADERMODE_VERTEXCOLOR;
2561                 }
2562                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2563                 {
2564                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2565                         if (r_shadow_bouncegriddirectional)
2566                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2567                 }
2568                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2569                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2570                 // when using alphatocoverage, we don't need alphakill
2571                 if (vid.allowalphatocoverage)
2572                 {
2573                         if (r_transparent_alphatocoverage.integer)
2574                         {
2575                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2576                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2577                         }
2578                         else
2579                                 GL_AlphaToCoverage(false);
2580                 }
2581         }
2582         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2583                 colormod = dummy_colormod;
2584         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2585                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2586         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2587                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2588         switch(vid.renderpath)
2589         {
2590         case RENDERPATH_D3D9:
2591 #ifdef SUPPORTD3D
2592                 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);
2593                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2594                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2595                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2596                 if (mode == SHADERMODE_LIGHTSOURCE)
2597                 {
2598                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2599                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2600                 }
2601                 else
2602                 {
2603                         if (mode == SHADERMODE_LIGHTDIRECTION)
2604                         {
2605                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2606                         }
2607                 }
2608                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2609                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2610                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2611                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2612                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2613
2614                 if (mode == SHADERMODE_LIGHTSOURCE)
2615                 {
2616                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2617                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2619                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2620                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2621
2622                         // additive passes are only darkened by fog, not tinted
2623                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2624                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2625                 }
2626                 else
2627                 {
2628                         if (mode == SHADERMODE_FLATCOLOR)
2629                         {
2630                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2631                         }
2632                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2633                         {
2634                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2635                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2636                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2637                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2638                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2639                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2640                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2641                         }
2642                         else
2643                         {
2644                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2645                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2646                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2647                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2648                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2649                         }
2650                         // additive passes are only darkened by fog, not tinted
2651                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2652                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2653                         else
2654                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2655                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2656                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2657                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2658                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2659                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2660                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2661                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2662                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2663                         if (mode == SHADERMODE_WATER)
2664                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2665                 }
2666                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2667                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2668                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2669                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2670                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2671                 if (rsurface.texture->pantstexture)
2672                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2673                 else
2674                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2675                 if (rsurface.texture->shirttexture)
2676                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2677                 else
2678                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2679                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2680                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2681                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2682                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2683                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2684                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2685                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2686                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2687                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2688                         );
2689                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2690                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2691                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2692                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2693
2694                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2695                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2696                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2697                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2698                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2699                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2700                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2701                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2702                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2703                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2704                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2705                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2706                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2707                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2708                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2709                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2710                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2711                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2712                 {
2713                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2714                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2715                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2716                 }
2717                 else
2718                 {
2719                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2720                 }
2721 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2722                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2723                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2724                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2725                 {
2726                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2727                         if (rsurface.rtlight)
2728                         {
2729                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2730                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2731                         }
2732                 }
2733 #endif
2734                 break;
2735         case RENDERPATH_D3D10:
2736                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2737                 break;
2738         case RENDERPATH_D3D11:
2739                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2740                 break;
2741         case RENDERPATH_GL20:
2742         case RENDERPATH_GLES2:
2743                 if (!vid.useinterleavedarrays)
2744                 {
2745                         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);
2746                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2747                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2748                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2749                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2750                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2751                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2752                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2753                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2754                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2755                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2756                 }
2757                 else
2758                 {
2759                         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);
2760                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2761                 }
2762                 // this has to be after RSurf_PrepareVerticesForBatch
2763                 if (rsurface.batchskeletaltransform3x4buffer)
2764                         permutation |= SHADERPERMUTATION_SKELETAL;
2765                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2766 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2767                 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);
2768 #endif
2769                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2770                 if (mode == SHADERMODE_LIGHTSOURCE)
2771                 {
2772                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2773                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2774                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2775                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2776                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2777                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2778         
2779                         // additive passes are only darkened by fog, not tinted
2780                         if (r_glsl_permutation->loc_FogColor >= 0)
2781                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2782                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2783                 }
2784                 else
2785                 {
2786                         if (mode == SHADERMODE_FLATCOLOR)
2787                         {
2788                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2789                         }
2790                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2791                         {
2792                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2793                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2794                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2795                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2796                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2797                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2798                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2799                         }
2800                         else
2801                         {
2802                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2803                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2804                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2805                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2806                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2807                         }
2808                         // additive passes are only darkened by fog, not tinted
2809                         if (r_glsl_permutation->loc_FogColor >= 0)
2810                         {
2811                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2812                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2813                                 else
2814                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2815                         }
2816                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2817                         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]);
2818                         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]);
2819                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2820                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2821                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2822                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2823                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2824                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2825                 }
2826                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2827                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2828                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2829                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2830                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2831
2832                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2833                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2834                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2835                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2836                 {
2837                         if (rsurface.texture->pantstexture)
2838                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2839                         else
2840                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2841                 }
2842                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2843                 {
2844                         if (rsurface.texture->shirttexture)
2845                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2846                         else
2847                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2848                 }
2849                 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]);
2850                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2851                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2852                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2853                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2854                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2855                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2856                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2857                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2858                         );
2859                 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);
2860                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2861                 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]);
2862                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2863                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2864                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2865
2866                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2867                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2868                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2869                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2870                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2871                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2872                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2873                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2874                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2875                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2876                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2877                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2878                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2879                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2880                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2881                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2882                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2883                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2884                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2885                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2886                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2887                 {
2888                         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);
2889                         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);
2890                         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);
2891                 }
2892                 else
2893                 {
2894                         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);
2895                 }
2896                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2897                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2898                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2899                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2900                 {
2901                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2902                         if (rsurface.rtlight)
2903                         {
2904                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2905                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2906                         }
2907                 }
2908                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2909                 CHECKGLERROR
2910                 break;
2911         case RENDERPATH_GL11:
2912         case RENDERPATH_GL13:
2913         case RENDERPATH_GLES1:
2914                 break;
2915         case RENDERPATH_SOFT:
2916                 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);
2917                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2918                 R_SetupShader_SetPermutationSoft(mode, permutation);
2919                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2920                 if (mode == SHADERMODE_LIGHTSOURCE)
2921                 {
2922                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2923                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2924                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2925                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2926                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2927                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2928         
2929                         // additive passes are only darkened by fog, not tinted
2930                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2931                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2932                 }
2933                 else
2934                 {
2935                         if (mode == SHADERMODE_FLATCOLOR)
2936                         {
2937                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2938                         }
2939                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2940                         {
2941                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2942                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2943                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2944                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2945                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2946                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2947                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2948                         }
2949                         else
2950                         {
2951                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2952                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2953                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2954                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2955                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2956                         }
2957                         // additive passes are only darkened by fog, not tinted
2958                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2959                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2960                         else
2961                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2962                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2963                         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]);
2964                         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]);
2965                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2966                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2967                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2968                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2969                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2970                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2971                 }
2972                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2973                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2974                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2975                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2976                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2977
2978                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2979                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2980                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2981                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2982                 {
2983                         if (rsurface.texture->pantstexture)
2984                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2985                         else
2986                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2987                 }
2988                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2989                 {
2990                         if (rsurface.texture->shirttexture)
2991                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2992                         else
2993                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2994                 }
2995                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2996                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2997                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2998                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2999                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3000                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3001                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3002                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3003                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3004                         );
3005                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3006                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3007                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3008                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3009
3010                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3011                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3012                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3013                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3014                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3015                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3016                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3017                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3018                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3019                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3020                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3021                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3022                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3023                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3024                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3025                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3026                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3027                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3028                 {
3029                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3030                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3031                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3032                 }
3033                 else
3034                 {
3035                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3036                 }
3037 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3038                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3039                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3040                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3041                 {
3042                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3043                         if (rsurface.rtlight)
3044                         {
3045                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3046                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3047                         }
3048                 }
3049                 break;
3050         }
3051 }
3052
3053 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3054 {
3055         // select a permutation of the lighting shader appropriate to this
3056         // combination of texture, entity, light source, and fogging, only use the
3057         // minimum features necessary to avoid wasting rendering time in the
3058         // fragment shader on features that are not being used
3059         unsigned int permutation = 0;
3060         unsigned int mode = 0;
3061         const float *lightcolorbase = rtlight->currentcolor;
3062         float ambientscale = rtlight->ambientscale;
3063         float diffusescale = rtlight->diffusescale;
3064         float specularscale = rtlight->specularscale;
3065         // this is the location of the light in view space
3066         vec3_t viewlightorigin;
3067         // this transforms from view space (camera) to light space (cubemap)
3068         matrix4x4_t viewtolight;
3069         matrix4x4_t lighttoview;
3070         float viewtolight16f[16];
3071         // light source
3072         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3073         if (rtlight->currentcubemap != r_texture_whitecube)
3074                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3075         if (diffusescale > 0)
3076                 permutation |= SHADERPERMUTATION_DIFFUSE;
3077         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3078                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3079         if (r_shadow_usingshadowmap2d)
3080         {
3081                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3082                 if (r_shadow_shadowmapvsdct)
3083                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3084
3085                 if (r_shadow_shadowmap2ddepthbuffer)
3086                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3087         }
3088         if (vid.allowalphatocoverage)
3089                 GL_AlphaToCoverage(false);
3090         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3091         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3092         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3093         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3094         switch(vid.renderpath)
3095         {
3096         case RENDERPATH_D3D9:
3097 #ifdef SUPPORTD3D
3098                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3099                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3100                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3101                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3102                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3103                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3104                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3105                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3106                 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);
3107                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3108                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3109
3110                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3111                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3112                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3113                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3114                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3115 #endif
3116                 break;
3117         case RENDERPATH_D3D10:
3118                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3119                 break;
3120         case RENDERPATH_D3D11:
3121                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3122                 break;
3123         case RENDERPATH_GL20:
3124         case RENDERPATH_GLES2:
3125                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3126                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3127                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3128                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3129                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3130                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3131                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3132                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3133                 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);
3134                 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]);
3135                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3136
3137                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3138                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3139                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3140                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3141                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3142                 break;
3143         case RENDERPATH_GL11:
3144         case RENDERPATH_GL13:
3145         case RENDERPATH_GLES1:
3146                 break;
3147         case RENDERPATH_SOFT:
3148                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3149                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3150                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3151                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3152                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3153                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3154                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3155                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3156                 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);
3157                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3158                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3159
3160                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3161                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3162                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3163                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3164                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3165                 break;
3166         }
3167 }
3168
3169 #define SKINFRAME_HASH 1024
3170
3171 typedef struct
3172 {
3173         unsigned int loadsequence; // incremented each level change
3174         memexpandablearray_t array;
3175         skinframe_t *hash[SKINFRAME_HASH];
3176 }
3177 r_skinframe_t;
3178 r_skinframe_t r_skinframe;
3179
3180 void R_SkinFrame_PrepareForPurge(void)
3181 {
3182         r_skinframe.loadsequence++;
3183         // wrap it without hitting zero
3184         if (r_skinframe.loadsequence >= 200)
3185                 r_skinframe.loadsequence = 1;
3186 }
3187
3188 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3189 {
3190         if (!skinframe)
3191                 return;
3192         // mark the skinframe as used for the purging code
3193         skinframe->loadsequence = r_skinframe.loadsequence;
3194 }
3195
3196 void R_SkinFrame_Purge(void)
3197 {
3198         int i;
3199         skinframe_t *s;
3200         for (i = 0;i < SKINFRAME_HASH;i++)
3201         {
3202                 for (s = r_skinframe.hash[i];s;s = s->next)
3203                 {
3204                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3205                         {
3206                                 if (s->merged == s->base)
3207                                         s->merged = NULL;
3208                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3209                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3210                                 R_PurgeTexture(s->merged);s->merged = NULL;
3211                                 R_PurgeTexture(s->base  );s->base   = NULL;
3212                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3213                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3214                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3215                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3216                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3217                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3218                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3219                                 s->loadsequence = 0;
3220                         }
3221                 }
3222         }
3223 }
3224
3225 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3226         skinframe_t *item;
3227         char basename[MAX_QPATH];
3228
3229         Image_StripImageExtension(name, basename, sizeof(basename));
3230
3231         if( last == NULL ) {
3232                 int hashindex;
3233                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3234                 item = r_skinframe.hash[hashindex];
3235         } else {
3236                 item = last->next;
3237         }
3238
3239         // linearly search through the hash bucket
3240         for( ; item ; item = item->next ) {
3241                 if( !strcmp( item->basename, basename ) ) {
3242                         return item;
3243                 }
3244         }
3245         return NULL;
3246 }
3247
3248 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3249 {
3250         skinframe_t *item;
3251         int hashindex;
3252         char basename[MAX_QPATH];
3253
3254         Image_StripImageExtension(name, basename, sizeof(basename));
3255
3256         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3257         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3258                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3259                         break;
3260
3261         if (!item) {
3262                 rtexture_t *dyntexture;
3263                 // check whether its a dynamic texture
3264                 dyntexture = CL_GetDynTexture( basename );
3265                 if (!add && !dyntexture)
3266                         return NULL;
3267                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3268                 memset(item, 0, sizeof(*item));
3269                 strlcpy(item->basename, basename, sizeof(item->basename));
3270                 item->base = dyntexture; // either NULL or dyntexture handle
3271                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3272                 item->comparewidth = comparewidth;
3273                 item->compareheight = compareheight;
3274                 item->comparecrc = comparecrc;
3275                 item->next = r_skinframe.hash[hashindex];
3276                 r_skinframe.hash[hashindex] = item;
3277         }
3278         else if (textureflags & TEXF_FORCE_RELOAD)
3279         {
3280                 rtexture_t *dyntexture;
3281                 // check whether its a dynamic texture
3282                 dyntexture = CL_GetDynTexture( basename );
3283                 if (!add && !dyntexture)
3284                         return NULL;
3285                 if (item->merged == item->base)
3286                         item->merged = NULL;
3287                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3288                 R_PurgeTexture(item->stain );item->stain  = NULL;
3289                 R_PurgeTexture(item->merged);item->merged = NULL;
3290                 R_PurgeTexture(item->base  );item->base   = NULL;
3291                 R_PurgeTexture(item->pants );item->pants  = NULL;
3292                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3293                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3294                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3295                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3296                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3297         R_PurgeTexture(item->reflect);item->reflect = NULL;
3298                 item->loadsequence = 0;
3299         }
3300         else if( item->base == NULL )
3301         {
3302                 rtexture_t *dyntexture;
3303                 // check whether its a dynamic texture
3304                 // 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]
3305                 dyntexture = CL_GetDynTexture( basename );
3306                 item->base = dyntexture; // either NULL or dyntexture handle
3307         }
3308
3309         R_SkinFrame_MarkUsed(item);
3310         return item;
3311 }
3312
3313 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3314         { \
3315                 unsigned long long avgcolor[5], wsum; \
3316                 int pix, comp, w; \
3317                 avgcolor[0] = 0; \
3318                 avgcolor[1] = 0; \
3319                 avgcolor[2] = 0; \
3320                 avgcolor[3] = 0; \
3321                 avgcolor[4] = 0; \
3322                 wsum = 0; \
3323                 for(pix = 0; pix < cnt; ++pix) \
3324                 { \
3325                         w = 0; \
3326                         for(comp = 0; comp < 3; ++comp) \
3327                                 w += getpixel; \
3328                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3329                         { \
3330                                 ++wsum; \
3331                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3332                                 w = getpixel; \
3333                                 for(comp = 0; comp < 3; ++comp) \
3334                                         avgcolor[comp] += getpixel * w; \
3335                                 avgcolor[3] += w; \
3336                         } \
3337                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3338                         avgcolor[4] += getpixel; \
3339                 } \
3340                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3341                         avgcolor[3] = 1; \
3342                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3343                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3344                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3345                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3346         }
3347
3348 extern cvar_t gl_picmip;
3349 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3350 {
3351         int j;
3352         unsigned char *pixels;
3353         unsigned char *bumppixels;
3354         unsigned char *basepixels = NULL;
3355         int basepixels_width = 0;
3356         int basepixels_height = 0;
3357         skinframe_t *skinframe;
3358         rtexture_t *ddsbase = NULL;
3359         qboolean ddshasalpha = false;
3360         float ddsavgcolor[4];
3361         char basename[MAX_QPATH];
3362         int miplevel = R_PicmipForFlags(textureflags);
3363         int savemiplevel = miplevel;
3364         int mymiplevel;
3365         char vabuf[1024];
3366
3367         if (cls.state == ca_dedicated)
3368                 return NULL;
3369
3370         // return an existing skinframe if already loaded
3371         // if loading of the first image fails, don't make a new skinframe as it
3372         // would cause all future lookups of this to be missing
3373         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3374         if (skinframe && skinframe->base)
3375                 return skinframe;
3376
3377         Image_StripImageExtension(name, basename, sizeof(basename));
3378
3379         // check for DDS texture file first
3380         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3381         {
3382                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3383                 if (basepixels == NULL)
3384                         return NULL;
3385         }
3386
3387         // FIXME handle miplevel
3388
3389         if (developer_loading.integer)
3390                 Con_Printf("loading skin \"%s\"\n", name);
3391
3392         // we've got some pixels to store, so really allocate this new texture now
3393         if (!skinframe)
3394                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3395         textureflags &= ~TEXF_FORCE_RELOAD;
3396         skinframe->stain = NULL;
3397         skinframe->merged = NULL;
3398         skinframe->base = NULL;
3399         skinframe->pants = NULL;
3400         skinframe->shirt = NULL;
3401         skinframe->nmap = NULL;
3402         skinframe->gloss = NULL;
3403         skinframe->glow = NULL;
3404         skinframe->fog = NULL;
3405         skinframe->reflect = NULL;
3406         skinframe->hasalpha = false;
3407         // we could store the q2animname here too
3408
3409         if (ddsbase)
3410         {
3411                 skinframe->base = ddsbase;
3412                 skinframe->hasalpha = ddshasalpha;
3413                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3414                 if (r_loadfog && skinframe->hasalpha)
3415                         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);
3416                 //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]);
3417         }
3418         else
3419         {
3420                 basepixels_width = image_width;
3421                 basepixels_height = image_height;
3422                 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);
3423                 if (textureflags & TEXF_ALPHA)
3424                 {
3425                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3426                         {
3427                                 if (basepixels[j] < 255)
3428                                 {
3429                                         skinframe->hasalpha = true;
3430                                         break;
3431                                 }
3432                         }
3433                         if (r_loadfog && skinframe->hasalpha)
3434                         {
3435                                 // has transparent pixels
3436                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3437                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3438                                 {
3439                                         pixels[j+0] = 255;
3440                                         pixels[j+1] = 255;
3441                                         pixels[j+2] = 255;
3442                                         pixels[j+3] = basepixels[j+3];
3443                                 }
3444                                 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);
3445                                 Mem_Free(pixels);
3446                         }
3447                 }
3448                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3449 #ifndef USE_GLES2
3450                 //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]);
3451                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3452                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3453                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3454                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3455 #endif
3456         }
3457
3458         if (r_loaddds)
3459         {
3460                 mymiplevel = savemiplevel;
3461                 if (r_loadnormalmap)
3462                         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);
3463                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3464                 if (r_loadgloss)
3465                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3466                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3467                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3468                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3469         }
3470
3471         // _norm is the name used by tenebrae and has been adopted as standard
3472         if (r_loadnormalmap && skinframe->nmap == NULL)
3473         {
3474                 mymiplevel = savemiplevel;
3475                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3476                 {
3477                         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);
3478                         Mem_Free(pixels);
3479                         pixels = NULL;
3480                 }
3481                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3482                 {
3483                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3484                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3485                         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);
3486                         Mem_Free(pixels);
3487                         Mem_Free(bumppixels);
3488                 }
3489                 else if (r_shadow_bumpscale_basetexture.value > 0)
3490                 {
3491                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3492                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3493                         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);
3494                         Mem_Free(pixels);
3495                 }
3496 #ifndef USE_GLES2
3497                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3498                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3499 #endif
3500         }
3501
3502         // _luma is supported only for tenebrae compatibility
3503         // _glow is the preferred name
3504         mymiplevel = savemiplevel;
3505         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))))
3506         {
3507                 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);
3508 #ifndef USE_GLES2
3509                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3510                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3511 #endif
3512                 Mem_Free(pixels);pixels = NULL;
3513         }
3514
3515         mymiplevel = savemiplevel;
3516         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3517         {
3518                 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);
3519 #ifndef USE_GLES2
3520                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3521                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3522 #endif
3523                 Mem_Free(pixels);
3524                 pixels = NULL;
3525         }
3526
3527         mymiplevel = savemiplevel;
3528         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3529         {
3530                 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);
3531 #ifndef USE_GLES2
3532                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3533                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3534 #endif
3535                 Mem_Free(pixels);
3536                 pixels = NULL;
3537         }
3538
3539         mymiplevel = savemiplevel;
3540         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3541         {
3542                 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);
3543 #ifndef USE_GLES2
3544                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3545                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3546 #endif
3547                 Mem_Free(pixels);
3548                 pixels = NULL;
3549         }
3550
3551         mymiplevel = savemiplevel;
3552         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3553         {
3554                 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);
3555 #ifndef USE_GLES2
3556                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3557                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3558 #endif
3559                 Mem_Free(pixels);
3560                 pixels = NULL;
3561         }
3562
3563         if (basepixels)
3564                 Mem_Free(basepixels);
3565
3566         return skinframe;
3567 }
3568
3569 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3570 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3571 {
3572         int i;
3573         unsigned char *temp1, *temp2;
3574         skinframe_t *skinframe;
3575         char vabuf[1024];
3576
3577         if (cls.state == ca_dedicated)
3578                 return NULL;
3579
3580         // if already loaded just return it, otherwise make a new skinframe
3581         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3582         if (skinframe->base)
3583                 return skinframe;
3584         textureflags &= ~TEXF_FORCE_RELOAD;
3585
3586         skinframe->stain = NULL;
3587         skinframe->merged = NULL;
3588         skinframe->base = NULL;
3589         skinframe->pants = NULL;
3590         skinframe->shirt = NULL;
3591         skinframe->nmap = NULL;
3592         skinframe->gloss = NULL;
3593         skinframe->glow = NULL;
3594         skinframe->fog = NULL;
3595         skinframe->reflect = NULL;
3596         skinframe->hasalpha = false;
3597
3598         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3599         if (!skindata)
3600                 return NULL;
3601
3602         if (developer_loading.integer)
3603                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3604
3605         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3606         {
3607                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3608                 temp2 = temp1 + width * height * 4;
3609                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3610                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3611                 Mem_Free(temp1);
3612         }
3613         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3614         if (textureflags & TEXF_ALPHA)
3615         {
3616                 for (i = 3;i < width * height * 4;i += 4)
3617                 {
3618                         if (skindata[i] < 255)
3619                         {
3620                                 skinframe->hasalpha = true;
3621                                 break;
3622                         }
3623                 }
3624                 if (r_loadfog && skinframe->hasalpha)
3625                 {
3626                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3627                         memcpy(fogpixels, skindata, width * height * 4);
3628                         for (i = 0;i < width * height * 4;i += 4)
3629                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3630                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3631                         Mem_Free(fogpixels);
3632                 }
3633         }
3634
3635         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3636         //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]);
3637
3638         return skinframe;
3639 }
3640
3641 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3642 {
3643         int i;
3644         int featuresmask;
3645         skinframe_t *skinframe;
3646
3647         if (cls.state == ca_dedicated)
3648                 return NULL;
3649
3650         // if already loaded just return it, otherwise make a new skinframe
3651         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3652         if (skinframe->base)
3653                 return skinframe;
3654         //textureflags &= ~TEXF_FORCE_RELOAD;
3655
3656         skinframe->stain = NULL;
3657         skinframe->merged = NULL;
3658         skinframe->base = NULL;
3659         skinframe->pants = NULL;
3660         skinframe->shirt = NULL;
3661         skinframe->nmap = NULL;
3662         skinframe->gloss = NULL;
3663         skinframe->glow = NULL;
3664         skinframe->fog = NULL;
3665         skinframe->reflect = NULL;
3666         skinframe->hasalpha = false;
3667
3668         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3669         if (!skindata)
3670                 return NULL;
3671
3672         if (developer_loading.integer)
3673                 Con_Printf("loading quake skin \"%s\"\n", name);
3674
3675         // 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)
3676         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3677         memcpy(skinframe->qpixels, skindata, width*height);
3678         skinframe->qwidth = width;
3679         skinframe->qheight = height;
3680
3681         featuresmask = 0;
3682         for (i = 0;i < width * height;i++)
3683                 featuresmask |= palette_featureflags[skindata[i]];
3684
3685         skinframe->hasalpha = false;
3686         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3687         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3688         skinframe->qgeneratemerged = true;
3689         skinframe->qgeneratebase = skinframe->qhascolormapping;
3690         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3691
3692         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3693         //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]);
3694
3695         return skinframe;
3696 }
3697
3698 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3699 {
3700         int width;
3701         int height;
3702         unsigned char *skindata;
3703         char vabuf[1024];
3704
3705         if (!skinframe->qpixels)
3706                 return;
3707
3708         if (!skinframe->qhascolormapping)
3709                 colormapped = false;
3710
3711         if (colormapped)
3712         {
3713                 if (!skinframe->qgeneratebase)
3714                         return;
3715         }
3716         else
3717         {
3718                 if (!skinframe->qgeneratemerged)
3719                         return;
3720         }
3721
3722         width = skinframe->qwidth;
3723         height = skinframe->qheight;
3724         skindata = skinframe->qpixels;
3725
3726         if (skinframe->qgeneratenmap)
3727         {
3728                 unsigned char *temp1, *temp2;
3729                 skinframe->qgeneratenmap = false;
3730                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3731                 temp2 = temp1 + width * height * 4;
3732                 // use either a custom palette or the quake palette
3733                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3734                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3735                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3736                 Mem_Free(temp1);
3737         }
3738
3739         if (skinframe->qgenerateglow)
3740         {
3741                 skinframe->qgenerateglow = false;
3742                 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
3743         }
3744
3745         if (colormapped)
3746         {
3747                 skinframe->qgeneratebase = false;
3748                 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);
3749                 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);
3750                 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);
3751         }
3752         else
3753         {
3754                 skinframe->qgeneratemerged = false;
3755                 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);
3756         }
3757
3758         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3759         {
3760                 Mem_Free(skinframe->qpixels);
3761                 skinframe->qpixels = NULL;
3762         }
3763 }
3764
3765 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)
3766 {
3767         int i;
3768         skinframe_t *skinframe;
3769         char vabuf[1024];
3770
3771         if (cls.state == ca_dedicated)
3772                 return NULL;
3773
3774         // if already loaded just return it, otherwise make a new skinframe
3775         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3776         if (skinframe->base)
3777                 return skinframe;
3778         textureflags &= ~TEXF_FORCE_RELOAD;
3779
3780         skinframe->stain = NULL;
3781         skinframe->merged = NULL;
3782         skinframe->base = NULL;
3783         skinframe->pants = NULL;
3784         skinframe->shirt = NULL;
3785         skinframe->nmap = NULL;
3786         skinframe->gloss = NULL;
3787         skinframe->glow = NULL;
3788         skinframe->fog = NULL;
3789         skinframe->reflect = NULL;
3790         skinframe->hasalpha = false;
3791
3792         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3793         if (!skindata)
3794                 return NULL;
3795
3796         if (developer_loading.integer)
3797                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3798
3799         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3800         if (textureflags & TEXF_ALPHA)
3801         {
3802                 for (i = 0;i < width * height;i++)
3803                 {
3804                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3805                         {
3806                                 skinframe->hasalpha = true;
3807                                 break;
3808                         }
3809                 }
3810                 if (r_loadfog && skinframe->hasalpha)
3811                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3812         }
3813
3814         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3815         //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]);
3816
3817         return skinframe;
3818 }
3819
3820 skinframe_t *R_SkinFrame_LoadMissing(void)
3821 {
3822         skinframe_t *skinframe;
3823
3824         if (cls.state == ca_dedicated)
3825                 return NULL;
3826
3827         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3828         skinframe->stain = NULL;
3829         skinframe->merged = NULL;
3830         skinframe->base = NULL;
3831         skinframe->pants = NULL;
3832         skinframe->shirt = NULL;
3833         skinframe->nmap = NULL;
3834         skinframe->gloss = NULL;
3835         skinframe->glow = NULL;
3836         skinframe->fog = NULL;
3837         skinframe->reflect = NULL;
3838         skinframe->hasalpha = false;
3839
3840         skinframe->avgcolor[0] = rand() / RAND_MAX;
3841         skinframe->avgcolor[1] = rand() / RAND_MAX;
3842         skinframe->avgcolor[2] = rand() / RAND_MAX;
3843         skinframe->avgcolor[3] = 1;
3844
3845         return skinframe;
3846 }
3847
3848 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3849 typedef struct suffixinfo_s
3850 {
3851         const char *suffix;
3852         qboolean flipx, flipy, flipdiagonal;
3853 }
3854 suffixinfo_t;
3855 static suffixinfo_t suffix[3][6] =
3856 {
3857         {
3858                 {"px",   false, false, false},
3859                 {"nx",   false, false, false},
3860                 {"py",   false, false, false},
3861                 {"ny",   false, false, false},
3862                 {"pz",   false, false, false},
3863                 {"nz",   false, false, false}
3864         },
3865         {
3866                 {"posx", false, false, false},
3867                 {"negx", false, false, false},
3868                 {"posy", false, false, false},
3869                 {"negy", false, false, false},
3870                 {"posz", false, false, false},
3871                 {"negz", false, false, false}
3872         },
3873         {
3874                 {"rt",    true, false,  true},
3875                 {"lf",   false,  true,  true},
3876                 {"ft",    true,  true, false},
3877                 {"bk",   false, false, false},
3878                 {"up",    true, false,  true},
3879                 {"dn",    true, false,  true}
3880         }
3881 };
3882
3883 static int componentorder[4] = {0, 1, 2, 3};
3884
3885 static rtexture_t *R_LoadCubemap(const char *basename)
3886 {
3887         int i, j, cubemapsize;
3888         unsigned char *cubemappixels, *image_buffer;
3889         rtexture_t *cubemaptexture;
3890         char name[256];
3891         // must start 0 so the first loadimagepixels has no requested width/height
3892         cubemapsize = 0;
3893         cubemappixels = NULL;
3894         cubemaptexture = NULL;
3895         // keep trying different suffix groups (posx, px, rt) until one loads
3896         for (j = 0;j < 3 && !cubemappixels;j++)
3897         {
3898                 // load the 6 images in the suffix group
3899                 for (i = 0;i < 6;i++)
3900                 {
3901                         // generate an image name based on the base and and suffix
3902                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3903                         // load it
3904                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3905                         {
3906                                 // an image loaded, make sure width and height are equal
3907                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3908                                 {
3909                                         // if this is the first image to load successfully, allocate the cubemap memory
3910                                         if (!cubemappixels && image_width >= 1)
3911                                         {
3912                                                 cubemapsize = image_width;
3913                                                 // note this clears to black, so unavailable sides are black
3914                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3915                                         }
3916                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3917                                         if (cubemappixels)
3918                                                 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);
3919                                 }
3920                                 else
3921                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3922                                 // free the image
3923                                 Mem_Free(image_buffer);
3924                         }
3925                 }
3926         }
3927         // if a cubemap loaded, upload it
3928         if (cubemappixels)
3929         {
3930                 if (developer_loading.integer)
3931                         Con_Printf("loading cubemap \"%s\"\n", basename);
3932
3933                 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);
3934                 Mem_Free(cubemappixels);
3935         }
3936         else
3937         {
3938                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3939                 if (developer_loading.integer)
3940                 {
3941                         Con_Printf("(tried tried images ");
3942                         for (j = 0;j < 3;j++)
3943                                 for (i = 0;i < 6;i++)
3944                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3945                         Con_Print(" and was unable to find any of them).\n");
3946                 }
3947         }
3948         return cubemaptexture;
3949 }
3950
3951 rtexture_t *R_GetCubemap(const char *basename)
3952 {
3953         int i;
3954         for (i = 0;i < r_texture_numcubemaps;i++)
3955                 if (r_texture_cubemaps[i] != NULL)
3956                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3957                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3958         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3959                 return r_texture_whitecube;
3960         r_texture_numcubemaps++;
3961         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3962         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3963         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3964         return r_texture_cubemaps[i]->texture;
3965 }
3966
3967 static void R_Main_FreeViewCache(void)
3968 {
3969         if (r_refdef.viewcache.entityvisible)
3970                 Mem_Free(r_refdef.viewcache.entityvisible);
3971         if (r_refdef.viewcache.world_pvsbits)
3972                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3973         if (r_refdef.viewcache.world_leafvisible)
3974                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3975         if (r_refdef.viewcache.world_surfacevisible)
3976                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3977         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3978 }
3979
3980 static void R_Main_ResizeViewCache(void)
3981 {
3982         int numentities = r_refdef.scene.numentities;
3983         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3984         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3985         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3986         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3987         if (r_refdef.viewcache.maxentities < numentities)
3988         {
3989                 r_refdef.viewcache.maxentities = numentities;
3990                 if (r_refdef.viewcache.entityvisible)
3991                         Mem_Free(r_refdef.viewcache.entityvisible);
3992                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3993         }
3994         if (r_refdef.viewcache.world_numclusters != numclusters)
3995         {
3996                 r_refdef.viewcache.world_numclusters = numclusters;
3997                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3998                 if (r_refdef.viewcache.world_pvsbits)
3999                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4000                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4001         }
4002         if (r_refdef.viewcache.world_numleafs != numleafs)
4003         {
4004                 r_refdef.viewcache.world_numleafs = numleafs;
4005                 if (r_refdef.viewcache.world_leafvisible)
4006                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4007                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4008         }
4009         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4010         {
4011                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4012                 if (r_refdef.viewcache.world_surfacevisible)
4013                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4014                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4015         }
4016 }
4017
4018 extern rtexture_t *loadingscreentexture;
4019 static void gl_main_start(void)
4020 {
4021         loadingscreentexture = NULL;
4022         r_texture_blanknormalmap = NULL;
4023         r_texture_white = NULL;
4024         r_texture_grey128 = NULL;
4025         r_texture_black = NULL;
4026         r_texture_whitecube = NULL;
4027         r_texture_normalizationcube = NULL;
4028         r_texture_fogattenuation = NULL;
4029         r_texture_fogheighttexture = NULL;
4030         r_texture_gammaramps = NULL;
4031         r_texture_numcubemaps = 0;
4032         r_uniformbufferalignment = 32;
4033
4034         r_loaddds = r_texture_dds_load.integer != 0;
4035         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4036
4037         switch(vid.renderpath)
4038         {
4039         case RENDERPATH_GL20:
4040         case RENDERPATH_D3D9:
4041         case RENDERPATH_D3D10:
4042         case RENDERPATH_D3D11:
4043         case RENDERPATH_SOFT:
4044         case RENDERPATH_GLES2:
4045                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4046                 Cvar_SetValueQuick(&gl_combine, 1);
4047                 Cvar_SetValueQuick(&r_glsl, 1);
4048                 r_loadnormalmap = true;
4049                 r_loadgloss = true;
4050                 r_loadfog = false;
4051 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4052                 if (vid.support.arb_uniform_buffer_object)
4053                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4054 #endif
4055                         break;
4056         case RENDERPATH_GL13:
4057         case RENDERPATH_GLES1:
4058                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4059                 Cvar_SetValueQuick(&gl_combine, 1);
4060                 Cvar_SetValueQuick(&r_glsl, 0);
4061                 r_loadnormalmap = false;
4062                 r_loadgloss = false;
4063                 r_loadfog = true;
4064                 break;
4065         case RENDERPATH_GL11:
4066                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4067                 Cvar_SetValueQuick(&gl_combine, 0);
4068                 Cvar_SetValueQuick(&r_glsl, 0);
4069                 r_loadnormalmap = false;
4070                 r_loadgloss = false;
4071                 r_loadfog = true;
4072                 break;
4073         }
4074
4075         R_AnimCache_Free();
4076         R_FrameData_Reset();
4077         R_BufferData_Reset();
4078
4079         r_numqueries = 0;
4080         r_maxqueries = 0;
4081         memset(r_queries, 0, sizeof(r_queries));
4082
4083         r_qwskincache = NULL;
4084         r_qwskincache_size = 0;
4085
4086         // due to caching of texture_t references, the collision cache must be reset
4087         Collision_Cache_Reset(true);
4088
4089         // set up r_skinframe loading system for textures
4090         memset(&r_skinframe, 0, sizeof(r_skinframe));
4091         r_skinframe.loadsequence = 1;
4092         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4093
4094         r_main_texturepool = R_AllocTexturePool();
4095         R_BuildBlankTextures();
4096         R_BuildNoTexture();
4097         if (vid.support.arb_texture_cube_map)
4098         {
4099                 R_BuildWhiteCube();
4100                 R_BuildNormalizationCube();
4101         }
4102         r_texture_fogattenuation = NULL;
4103         r_texture_fogheighttexture = NULL;
4104         r_texture_gammaramps = NULL;
4105         //r_texture_fogintensity = NULL;
4106         memset(&r_fb, 0, sizeof(r_fb));
4107         r_glsl_permutation = NULL;
4108         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4109         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4110         glslshaderstring = NULL;
4111 #ifdef SUPPORTD3D
4112         r_hlsl_permutation = NULL;
4113         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4114         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4115 #endif
4116         hlslshaderstring = NULL;
4117         memset(&r_svbsp, 0, sizeof (r_svbsp));
4118
4119         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4120         r_texture_numcubemaps = 0;
4121
4122         r_refdef.fogmasktable_density = 0;
4123
4124 #ifdef __ANDROID__
4125         // For Steelstorm Android
4126         // FIXME CACHE the program and reload
4127         // FIXME see possible combinations for SS:BR android
4128         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4129         R_SetupShader_SetPermutationGLSL(0, 12);
4130         R_SetupShader_SetPermutationGLSL(0, 13);
4131         R_SetupShader_SetPermutationGLSL(0, 8388621);
4132         R_SetupShader_SetPermutationGLSL(3, 0);
4133         R_SetupShader_SetPermutationGLSL(3, 2048);
4134         R_SetupShader_SetPermutationGLSL(5, 0);
4135         R_SetupShader_SetPermutationGLSL(5, 2);
4136         R_SetupShader_SetPermutationGLSL(5, 2048);
4137         R_SetupShader_SetPermutationGLSL(5, 8388608);
4138         R_SetupShader_SetPermutationGLSL(11, 1);
4139         R_SetupShader_SetPermutationGLSL(11, 2049);
4140         R_SetupShader_SetPermutationGLSL(11, 8193);
4141         R_SetupShader_SetPermutationGLSL(11, 10241);
4142         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4143 #endif
4144 }
4145
4146 static void gl_main_shutdown(void)
4147 {
4148         R_AnimCache_Free();
4149         R_FrameData_Reset();
4150         R_BufferData_Reset();
4151
4152         R_Main_FreeViewCache();
4153
4154         switch(vid.renderpath)
4155         {
4156         case RENDERPATH_GL11:
4157         case RENDERPATH_GL13:
4158         case RENDERPATH_GL20:
4159         case RENDERPATH_GLES1:
4160         case RENDERPATH_GLES2:
4161 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4162                 if (r_maxqueries)
4163                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4164 #endif
4165                 break;
4166         case RENDERPATH_D3D9:
4167                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4168                 break;
4169         case RENDERPATH_D3D10:
4170                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4171                 break;
4172         case RENDERPATH_D3D11:
4173                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4174                 break;
4175         case RENDERPATH_SOFT:
4176                 break;
4177         }
4178
4179         r_numqueries = 0;
4180         r_maxqueries = 0;
4181         memset(r_queries, 0, sizeof(r_queries));
4182
4183         r_qwskincache = NULL;
4184         r_qwskincache_size = 0;
4185
4186         // clear out the r_skinframe state
4187         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4188         memset(&r_skinframe, 0, sizeof(r_skinframe));
4189
4190         if (r_svbsp.nodes)
4191                 Mem_Free(r_svbsp.nodes);
4192         memset(&r_svbsp, 0, sizeof (r_svbsp));
4193         R_FreeTexturePool(&r_main_texturepool);
4194         loadingscreentexture = NULL;
4195         r_texture_blanknormalmap = NULL;
4196         r_texture_white = NULL;
4197         r_texture_grey128 = NULL;
4198         r_texture_black = NULL;
4199         r_texture_whitecube = NULL;
4200         r_texture_normalizationcube = NULL;
4201         r_texture_fogattenuation = NULL;
4202         r_texture_fogheighttexture = NULL;
4203         r_texture_gammaramps = NULL;
4204         r_texture_numcubemaps = 0;
4205         //r_texture_fogintensity = NULL;
4206         memset(&r_fb, 0, sizeof(r_fb));
4207         R_GLSL_Restart_f();
4208
4209         r_glsl_permutation = NULL;
4210         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4211         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4212         glslshaderstring = NULL;
4213 #ifdef SUPPORTD3D
4214         r_hlsl_permutation = NULL;
4215         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4216         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4217 #endif
4218         hlslshaderstring = NULL;
4219 }
4220
4221 static void gl_main_newmap(void)
4222 {
4223         // FIXME: move this code to client
4224         char *entities, entname[MAX_QPATH];
4225         if (r_qwskincache)
4226                 Mem_Free(r_qwskincache);
4227         r_qwskincache = NULL;
4228         r_qwskincache_size = 0;
4229         if (cl.worldmodel)
4230         {
4231                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4232                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4233                 {
4234                         CL_ParseEntityLump(entities);
4235                         Mem_Free(entities);
4236                         return;
4237                 }
4238                 if (cl.worldmodel->brush.entities)
4239                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4240         }
4241         R_Main_FreeViewCache();
4242
4243         R_FrameData_Reset();
4244         R_BufferData_Reset();
4245 }
4246
4247 void GL_Main_Init(void)
4248 {
4249         int i;
4250         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4251
4252         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4253         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4254         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4255         if (gamemode == GAME_NEHAHRA)
4256         {
4257                 Cvar_RegisterVariable (&gl_fogenable);
4258                 Cvar_RegisterVariable (&gl_fogdensity);
4259                 Cvar_RegisterVariable (&gl_fogred);
4260                 Cvar_RegisterVariable (&gl_foggreen);
4261                 Cvar_RegisterVariable (&gl_fogblue);
4262                 Cvar_RegisterVariable (&gl_fogstart);
4263                 Cvar_RegisterVariable (&gl_fogend);
4264                 Cvar_RegisterVariable (&gl_skyclip);
4265         }
4266         Cvar_RegisterVariable(&r_motionblur);
4267         Cvar_RegisterVariable(&r_damageblur);
4268         Cvar_RegisterVariable(&r_motionblur_averaging);
4269         Cvar_RegisterVariable(&r_motionblur_randomize);
4270         Cvar_RegisterVariable(&r_motionblur_minblur);
4271         Cvar_RegisterVariable(&r_motionblur_maxblur);
4272         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4273         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4274         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4275         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4276         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4277         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4278         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4279         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4280         Cvar_RegisterVariable(&r_equalize_entities_by);
4281         Cvar_RegisterVariable(&r_equalize_entities_to);
4282         Cvar_RegisterVariable(&r_depthfirst);
4283         Cvar_RegisterVariable(&r_useinfinitefarclip);
4284         Cvar_RegisterVariable(&r_farclip_base);
4285         Cvar_RegisterVariable(&r_farclip_world);
4286         Cvar_RegisterVariable(&r_nearclip);
4287         Cvar_RegisterVariable(&r_deformvertexes);
4288         Cvar_RegisterVariable(&r_transparent);
4289         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4290         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4291         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4292         Cvar_RegisterVariable(&r_showoverdraw);
4293         Cvar_RegisterVariable(&r_showbboxes);
4294         Cvar_RegisterVariable(&r_showsurfaces);
4295         Cvar_RegisterVariable(&r_showtris);
4296         Cvar_RegisterVariable(&r_shownormals);
4297         Cvar_RegisterVariable(&r_showlighting);
4298         Cvar_RegisterVariable(&r_showshadowvolumes);
4299         Cvar_RegisterVariable(&r_showcollisionbrushes);
4300         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4301         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4302         Cvar_RegisterVariable(&r_showdisabledepthtest);
4303         Cvar_RegisterVariable(&r_drawportals);
4304         Cvar_RegisterVariable(&r_drawentities);
4305         Cvar_RegisterVariable(&r_draw2d);
4306         Cvar_RegisterVariable(&r_drawworld);
4307         Cvar_RegisterVariable(&r_cullentities_trace);
4308         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4309         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4310         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4311         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4312         Cvar_RegisterVariable(&r_sortentities);
4313         Cvar_RegisterVariable(&r_drawviewmodel);
4314         Cvar_RegisterVariable(&r_drawexteriormodel);
4315         Cvar_RegisterVariable(&r_speeds);
4316         Cvar_RegisterVariable(&r_fullbrights);
4317         Cvar_RegisterVariable(&r_wateralpha);
4318         Cvar_RegisterVariable(&r_dynamic);
4319         Cvar_RegisterVariable(&r_fakelight);
4320         Cvar_RegisterVariable(&r_fakelight_intensity);
4321         Cvar_RegisterVariable(&r_fullbright);
4322         Cvar_RegisterVariable(&r_shadows);
4323         Cvar_RegisterVariable(&r_shadows_darken);
4324         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4325         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4326         Cvar_RegisterVariable(&r_shadows_throwdistance);
4327         Cvar_RegisterVariable(&r_shadows_throwdirection);
4328         Cvar_RegisterVariable(&r_shadows_focus);
4329         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4330         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4331         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4332         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4333         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4334         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4335         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4336         Cvar_RegisterVariable(&r_fog_exp2);
4337         Cvar_RegisterVariable(&r_fog_clear);
4338         Cvar_RegisterVariable(&r_drawfog);
4339         Cvar_RegisterVariable(&r_transparentdepthmasking);
4340         Cvar_RegisterVariable(&r_transparent_sortmindist);
4341         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4342         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4343         Cvar_RegisterVariable(&r_texture_dds_load);
4344         Cvar_RegisterVariable(&r_texture_dds_save);
4345         Cvar_RegisterVariable(&r_textureunits);
4346         Cvar_RegisterVariable(&gl_combine);
4347         Cvar_RegisterVariable(&r_usedepthtextures);
4348         Cvar_RegisterVariable(&r_viewfbo);
4349         Cvar_RegisterVariable(&r_viewscale);
4350         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4351         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4352         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4353         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4354         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4355         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4356         Cvar_RegisterVariable(&r_glsl);
4357         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4358         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4359         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4360         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4361         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4362         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4363         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4364         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4365         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4366         Cvar_RegisterVariable(&r_glsl_postprocess);
4367         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4368         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4369         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4370         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4371         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4372         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4373         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4374         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4375         Cvar_RegisterVariable(&r_celshading);
4376         Cvar_RegisterVariable(&r_celoutlines);
4377
4378         Cvar_RegisterVariable(&r_water);
4379         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4380         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4381         Cvar_RegisterVariable(&r_water_clippingplanebias);
4382         Cvar_RegisterVariable(&r_water_refractdistort);
4383         Cvar_RegisterVariable(&r_water_reflectdistort);
4384         Cvar_RegisterVariable(&r_water_scissormode);
4385         Cvar_RegisterVariable(&r_water_lowquality);
4386         Cvar_RegisterVariable(&r_water_hideplayer);
4387         Cvar_RegisterVariable(&r_water_fbo);
4388
4389         Cvar_RegisterVariable(&r_lerpsprites);
4390         Cvar_RegisterVariable(&r_lerpmodels);
4391         Cvar_RegisterVariable(&r_lerplightstyles);
4392         Cvar_RegisterVariable(&r_waterscroll);
4393         Cvar_RegisterVariable(&r_bloom);
4394         Cvar_RegisterVariable(&r_bloom_colorscale);
4395         Cvar_RegisterVariable(&r_bloom_brighten);
4396         Cvar_RegisterVariable(&r_bloom_blur);
4397         Cvar_RegisterVariable(&r_bloom_resolution);
4398         Cvar_RegisterVariable(&r_bloom_colorexponent);
4399         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4400         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4401         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4402         Cvar_RegisterVariable(&r_hdr_glowintensity);
4403         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4404         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4405         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4406         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4407         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4408         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4409         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4410         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4411         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4412         Cvar_RegisterVariable(&developer_texturelogging);
4413         Cvar_RegisterVariable(&gl_lightmaps);
4414         Cvar_RegisterVariable(&r_test);
4415         Cvar_RegisterVariable(&r_batch_multidraw);
4416         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4417         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4418         Cvar_RegisterVariable(&r_glsl_skeletal);
4419         Cvar_RegisterVariable(&r_glsl_saturation);
4420         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4421         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4422         Cvar_RegisterVariable(&r_framedatasize);
4423         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4424                 Cvar_RegisterVariable(&r_buffermegs[i]);
4425         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4426         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4427                 Cvar_SetValue("r_fullbrights", 0);
4428 #ifdef DP_MOBILETOUCH
4429         // GLES devices have terrible depth precision in general, so...
4430         Cvar_SetValueQuick(&r_nearclip, 4);
4431         Cvar_SetValueQuick(&r_farclip_base, 4096);
4432         Cvar_SetValueQuick(&r_farclip_world, 0);
4433         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4434 #endif
4435         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4436 }
4437
4438 void Render_Init(void)
4439 {
4440         gl_backend_init();
4441         R_Textures_Init();
4442         GL_Main_Init();
4443         Font_Init();
4444         GL_Draw_Init();
4445         R_Shadow_Init();
4446         R_Sky_Init();
4447         GL_Surf_Init();
4448         Sbar_Init();
4449         R_Particles_Init();
4450         R_Explosion_Init();
4451         R_LightningBeams_Init();
4452         Mod_RenderInit();
4453 }
4454
4455 /*
4456 ===============
4457 GL_Init
4458 ===============
4459 */
4460 #ifndef USE_GLES2
4461 extern char *ENGINE_EXTENSIONS;
4462 void GL_Init (void)
4463 {
4464         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4465         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4466         gl_version = (const char *)qglGetString(GL_VERSION);
4467         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4468
4469         if (!gl_extensions)
4470                 gl_extensions = "";
4471         if (!gl_platformextensions)
4472                 gl_platformextensions = "";
4473
4474         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4475         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4476         Con_Printf("GL_VERSION: %s\n", gl_version);
4477         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4478         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4479
4480         VID_CheckExtensions();
4481
4482         // LordHavoc: report supported extensions
4483 #ifdef CONFIG_MENU
4484         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4485 #else
4486         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4487 #endif
4488
4489         // clear to black (loading plaque will be seen over this)
4490         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4491 }
4492 #endif
4493
4494 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4495 {
4496         int i;
4497         mplane_t *p;
4498         if (r_trippy.integer)
4499                 return false;
4500         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4501         {
4502                 p = r_refdef.view.frustum + i;
4503                 switch(p->signbits)
4504                 {
4505                 default:
4506                 case 0:
4507                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4508                                 return true;
4509                         break;
4510                 case 1:
4511                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4512                                 return true;
4513                         break;
4514                 case 2:
4515                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4516                                 return true;
4517                         break;
4518                 case 3:
4519                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4520                                 return true;
4521                         break;
4522                 case 4:
4523                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4524                                 return true;
4525                         break;
4526                 case 5:
4527                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4528                                 return true;
4529                         break;
4530                 case 6:
4531                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4532                                 return true;
4533                         break;
4534                 case 7:
4535                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4536                                 return true;
4537                         break;
4538                 }
4539         }
4540         return false;
4541 }
4542
4543 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4544 {
4545         int i;
4546         const mplane_t *p;
4547         if (r_trippy.integer)
4548                 return false;
4549         for (i = 0;i < numplanes;i++)
4550         {
4551                 p = planes + i;
4552                 switch(p->signbits)
4553                 {
4554                 default:
4555                 case 0:
4556                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4557                                 return true;
4558                         break;
4559                 case 1:
4560                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4561                                 return true;
4562                         break;
4563                 case 2:
4564                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4565                                 return true;
4566                         break;
4567                 case 3:
4568                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4569                                 return true;
4570                         break;
4571                 case 4:
4572                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4573                                 return true;
4574                         break;
4575                 case 5:
4576                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4577                                 return true;
4578                         break;
4579                 case 6:
4580                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4581                                 return true;
4582                         break;
4583                 case 7:
4584                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4585                                 return true;
4586                         break;
4587                 }
4588         }
4589         return false;
4590 }
4591
4592 //==================================================================================
4593
4594 // LordHavoc: this stores temporary data used within the same frame
4595
4596 typedef struct r_framedata_mem_s
4597 {
4598         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4599         size_t size; // how much usable space
4600         size_t current; // how much space in use
4601         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4602         size_t wantedsize; // how much space was allocated
4603         unsigned char *data; // start of real data (16byte aligned)
4604 }
4605 r_framedata_mem_t;
4606
4607 static r_framedata_mem_t *r_framedata_mem;
4608
4609 void R_FrameData_Reset(void)
4610 {
4611         while (r_framedata_mem)
4612         {
4613                 r_framedata_mem_t *next = r_framedata_mem->purge;
4614                 Mem_Free(r_framedata_mem);
4615                 r_framedata_mem = next;
4616         }
4617 }
4618
4619 static void R_FrameData_Resize(qboolean mustgrow)
4620 {
4621         size_t wantedsize;
4622         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4623         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4624         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4625         {
4626                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4627                 newmem->wantedsize = wantedsize;
4628                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4629                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4630                 newmem->current = 0;
4631                 newmem->mark = 0;
4632                 newmem->purge = r_framedata_mem;
4633                 r_framedata_mem = newmem;
4634         }
4635 }
4636
4637 void R_FrameData_NewFrame(void)
4638 {
4639         R_FrameData_Resize(false);
4640         if (!r_framedata_mem)
4641                 return;
4642         // if we ran out of space on the last frame, free the old memory now
4643         while (r_framedata_mem->purge)
4644         {
4645                 // repeatedly remove the second item in the list, leaving only head
4646                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4647                 Mem_Free(r_framedata_mem->purge);
4648                 r_framedata_mem->purge = next;
4649         }
4650         // reset the current mem pointer
4651         r_framedata_mem->current = 0;
4652         r_framedata_mem->mark = 0;
4653 }
4654
4655 void *R_FrameData_Alloc(size_t size)
4656 {
4657         void *data;
4658         float newvalue;
4659
4660         // align to 16 byte boundary - the data pointer is already aligned, so we
4661         // only need to ensure the size of every allocation is also aligned
4662         size = (size + 15) & ~15;
4663
4664         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4665         {
4666                 // emergency - we ran out of space, allocate more memory
4667                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4668                 // this might not be a growing it, but we'll allocate another buffer every time
4669                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4670                 R_FrameData_Resize(true);
4671         }
4672
4673         data = r_framedata_mem->data + r_framedata_mem->current;
4674         r_framedata_mem->current += size;
4675
4676         // count the usage for stats
4677         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4678         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4679
4680         return (void *)data;
4681 }
4682
4683 void *R_FrameData_Store(size_t size, void *data)
4684 {
4685         void *d = R_FrameData_Alloc(size);
4686         if (d && data)
4687                 memcpy(d, data, size);
4688         return d;
4689 }
4690
4691 void R_FrameData_SetMark(void)
4692 {
4693         if (!r_framedata_mem)
4694                 return;
4695         r_framedata_mem->mark = r_framedata_mem->current;
4696 }
4697
4698 void R_FrameData_ReturnToMark(void)
4699 {
4700         if (!r_framedata_mem)
4701                 return;
4702         r_framedata_mem->current = r_framedata_mem->mark;
4703 }
4704
4705 //==================================================================================
4706
4707 // avoid reusing the same buffer objects on consecutive frames
4708 #define R_BUFFERDATA_CYCLE 3
4709
4710 typedef struct r_bufferdata_buffer_s
4711 {
4712         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4713         size_t size; // how much usable space
4714         size_t current; // how much space in use
4715         r_meshbuffer_t *buffer; // the buffer itself
4716 }
4717 r_bufferdata_buffer_t;
4718
4719 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4720 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4721
4722 /// frees all dynamic buffers
4723 void R_BufferData_Reset(void)
4724 {
4725         int cycle, type;
4726         r_bufferdata_buffer_t **p, *mem;
4727         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4728         {
4729                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4730                 {
4731                         // free all buffers
4732                         p = &r_bufferdata_buffer[cycle][type];
4733                         while (*p)
4734                         {
4735                                 mem = *p;
4736                                 *p = (*p)->purge;
4737                                 if (mem->buffer)
4738                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4739                                 Mem_Free(mem);
4740                         }
4741                 }
4742         }
4743 }
4744
4745 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4746 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4747 {
4748         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4749         size_t size;
4750         float newvalue = r_buffermegs[type].value;
4751
4752         // increase the cvar if we have to (but only if we already have a mem)
4753         if (mustgrow && mem)
4754                 newvalue *= 2.0f;
4755         newvalue = bound(0.25f, newvalue, 256.0f);
4756         while (newvalue * 1024*1024 < minsize)
4757                 newvalue *= 2.0f;
4758
4759         // clamp the cvar to valid range
4760         newvalue = bound(0.25f, newvalue, 256.0f);
4761         if (r_buffermegs[type].value != newvalue)
4762                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4763
4764         // calculate size in bytes
4765         size = (size_t)(newvalue * 1024*1024);
4766         size = bound(131072, size, 256*1024*1024);
4767
4768         // allocate a new buffer if the size is different (purge old one later)
4769         // or if we were told we must grow the buffer
4770         if (!mem || mem->size != size || mustgrow)
4771         {
4772                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4773                 mem->size = size;
4774                 mem->current = 0;
4775                 if (type == R_BUFFERDATA_VERTEX)
4776                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4777                 else if (type == R_BUFFERDATA_INDEX16)
4778                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4779                 else if (type == R_BUFFERDATA_INDEX32)
4780                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4781                 else if (type == R_BUFFERDATA_UNIFORM)
4782                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4783                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4784                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4785         }
4786 }
4787
4788 void R_BufferData_NewFrame(void)
4789 {
4790         int type;
4791         r_bufferdata_buffer_t **p, *mem;
4792         // cycle to the next frame's buffers
4793         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4794         // if we ran out of space on the last time we used these buffers, free the old memory now
4795         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4796         {
4797                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4798                 {
4799                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4800                         // free all but the head buffer, this is how we recycle obsolete
4801                         // buffers after they are no longer in use
4802                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4803                         while (*p)
4804                         {
4805                                 mem = *p;
4806                                 *p = (*p)->purge;
4807                                 if (mem->buffer)
4808                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4809                                 Mem_Free(mem);
4810                         }
4811                         // reset the current offset
4812                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4813                 }
4814         }
4815 }
4816
4817 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4818 {
4819         r_bufferdata_buffer_t *mem;
4820         int offset = 0;
4821         int padsize;
4822
4823         *returnbufferoffset = 0;
4824
4825         // align size to a byte boundary appropriate for the buffer type, this
4826         // makes all allocations have aligned start offsets
4827         if (type == R_BUFFERDATA_UNIFORM)
4828                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4829         else
4830                 padsize = (datasize + 15) & ~15;
4831
4832         // if we ran out of space in this buffer we must allocate a new one
4833         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)
4834                 R_BufferData_Resize(type, true, padsize);
4835
4836         // if the resize did not give us enough memory, fail
4837         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)
4838                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4839
4840         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4841         offset = (int)mem->current;
4842         mem->current += padsize;
4843
4844         // upload the data to the buffer at the chosen offset
4845         if (offset == 0)
4846                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4847         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4848
4849         // count the usage for stats
4850         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4851         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4852
4853         // return the buffer offset
4854         *returnbufferoffset = offset;
4855
4856         return mem->buffer;
4857 }
4858
4859 //==================================================================================
4860
4861 // LordHavoc: animcache originally written by Echon, rewritten since then
4862
4863 /**
4864  * Animation cache prevents re-generating mesh data for an animated model
4865  * multiple times in one frame for lighting, shadowing, reflections, etc.
4866  */
4867
4868 void R_AnimCache_Free(void)
4869 {
4870 }
4871
4872 void R_AnimCache_ClearCache(void)
4873 {
4874         int i;
4875         entity_render_t *ent;
4876
4877         for (i = 0;i < r_refdef.scene.numentities;i++)
4878         {
4879                 ent = r_refdef.scene.entities[i];
4880                 ent->animcache_vertex3f = NULL;
4881                 ent->animcache_vertex3f_vertexbuffer = NULL;
4882                 ent->animcache_vertex3f_bufferoffset = 0;
4883                 ent->animcache_normal3f = NULL;
4884                 ent->animcache_normal3f_vertexbuffer = NULL;
4885                 ent->animcache_normal3f_bufferoffset = 0;
4886                 ent->animcache_svector3f = NULL;
4887                 ent->animcache_svector3f_vertexbuffer = NULL;
4888                 ent->animcache_svector3f_bufferoffset = 0;
4889                 ent->animcache_tvector3f = NULL;
4890                 ent->animcache_tvector3f_vertexbuffer = NULL;
4891                 ent->animcache_tvector3f_bufferoffset = 0;
4892                 ent->animcache_vertexmesh = NULL;
4893                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4894                 ent->animcache_vertexmesh_bufferoffset = 0;
4895                 ent->animcache_skeletaltransform3x4 = NULL;
4896                 ent->animcache_skeletaltransform3x4buffer = NULL;
4897                 ent->animcache_skeletaltransform3x4offset = 0;
4898                 ent->animcache_skeletaltransform3x4size = 0;
4899         }
4900 }
4901
4902 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4903 {
4904         int i;
4905
4906         // check if we need the meshbuffers
4907         if (!vid.useinterleavedarrays)
4908                 return;
4909
4910         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4911                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4912         // TODO: upload vertexbuffer?
4913         if (ent->animcache_vertexmesh)
4914         {
4915                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4916                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4917                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4918                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4919                 for (i = 0;i < numvertices;i++)
4920                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4921                 if (ent->animcache_svector3f)
4922                         for (i = 0;i < numvertices;i++)
4923                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4924                 if (ent->animcache_tvector3f)
4925                         for (i = 0;i < numvertices;i++)
4926                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4927                 if (ent->animcache_normal3f)
4928                         for (i = 0;i < numvertices;i++)
4929                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4930         }
4931 }
4932
4933 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4934 {
4935         dp_model_t *model = ent->model;
4936         int numvertices;
4937
4938         // see if this ent is worth caching
4939         if (!model || !model->Draw || !model->AnimateVertices)
4940                 return false;
4941         // nothing to cache if it contains no animations and has no skeleton
4942         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4943                 return false;
4944         // see if it is already cached for gpuskeletal
4945         if (ent->animcache_skeletaltransform3x4)
4946                 return false;
4947         // see if it is already cached as a mesh
4948         if (ent->animcache_vertex3f)
4949         {
4950                 // check if we need to add normals or tangents
4951                 if (ent->animcache_normal3f)
4952                         wantnormals = false;
4953                 if (ent->animcache_svector3f)
4954                         wanttangents = false;
4955                 if (!wantnormals && !wanttangents)
4956                         return false;
4957         }
4958
4959         // check which kind of cache we need to generate
4960         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4961         {
4962                 // cache the skeleton so the vertex shader can use it
4963                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4964                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4965                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4966                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4967                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4968                 // note: this can fail if the buffer is at the grow limit
4969                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4970                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4971         }
4972         else if (ent->animcache_vertex3f)
4973         {
4974                 // mesh was already cached but we may need to add normals/tangents
4975                 // (this only happens with multiple views, reflections, cameras, etc)
4976                 if (wantnormals || wanttangents)
4977                 {
4978                         numvertices = model->surfmesh.num_vertices;
4979                         if (wantnormals)
4980                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4981                         if (wanttangents)
4982                         {
4983                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4984                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4985                         }
4986                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4987                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4988                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4989                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4990                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4991                 }
4992         }
4993         else
4994         {
4995                 // generate mesh cache
4996                 numvertices = model->surfmesh.num_vertices;
4997                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4998                 if (wantnormals)
4999                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5000                 if (wanttangents)
5001                 {
5002                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5003                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5004                 }
5005                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5006                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5007                 if (wantnormals || wanttangents)
5008                 {
5009                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5010                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5011                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5012                 }
5013                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5014                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5015                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5016         }
5017         return true;
5018 }
5019
5020 void R_AnimCache_CacheVisibleEntities(void)
5021 {
5022         int i;
5023         qboolean wantnormals = true;
5024         qboolean wanttangents = !r_showsurfaces.integer;
5025
5026         switch(vid.renderpath)
5027         {
5028         case RENDERPATH_GL20:
5029         case RENDERPATH_D3D9:
5030         case RENDERPATH_D3D10:
5031         case RENDERPATH_D3D11:
5032         case RENDERPATH_GLES2:
5033                 break;
5034         case RENDERPATH_GL11:
5035         case RENDERPATH_GL13:
5036         case RENDERPATH_GLES1:
5037                 wanttangents = false;
5038                 break;
5039         case RENDERPATH_SOFT:
5040                 break;
5041         }
5042
5043         if (r_shownormals.integer)
5044                 wanttangents = wantnormals = true;
5045
5046         // TODO: thread this
5047         // NOTE: R_PrepareRTLights() also caches entities
5048
5049         for (i = 0;i < r_refdef.scene.numentities;i++)
5050                 if (r_refdef.viewcache.entityvisible[i])
5051                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5052 }
5053
5054 //==================================================================================
5055
5056 extern cvar_t r_overheadsprites_pushback;
5057
5058 static void R_View_UpdateEntityLighting (void)
5059 {
5060         int i;
5061         entity_render_t *ent;
5062         vec3_t tempdiffusenormal, avg;
5063         vec_t f, fa, fd, fdd;
5064         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5065
5066         for (i = 0;i < r_refdef.scene.numentities;i++)
5067         {
5068                 ent = r_refdef.scene.entities[i];
5069
5070                 // skip unseen models
5071                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5072                         continue;
5073
5074                 // skip bsp models
5075                 if (ent->model && ent->model == cl.worldmodel)
5076                 {
5077                         // TODO: use modellight for r_ambient settings on world?
5078                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5079                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5080                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5081                         continue;
5082                 }
5083                 
5084                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5085                 {
5086                         // aleady updated by CSQC
5087                         // TODO: force modellight on BSP models in this case?
5088                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5089                 }
5090                 else
5091                 {
5092                         // fetch the lighting from the worldmodel data
5093                         VectorClear(ent->modellight_ambient);
5094                         VectorClear(ent->modellight_diffuse);
5095                         VectorClear(tempdiffusenormal);
5096                         if (ent->flags & RENDER_LIGHT)
5097                         {
5098                                 vec3_t org;
5099                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5100
5101                                 // complete lightning for lit sprites
5102                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5103                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5104                                 {
5105                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5106                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5107                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5108                                 }
5109                                 else
5110                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5111
5112                                 if(ent->flags & RENDER_EQUALIZE)
5113                                 {
5114                                         // first fix up ambient lighting...
5115                                         if(r_equalize_entities_minambient.value > 0)
5116                                         {
5117                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5118                                                 if(fd > 0)
5119                                                 {
5120                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5121                                                         if(fa < r_equalize_entities_minambient.value * fd)
5122                                                         {
5123                                                                 // solve:
5124                                                                 //   fa'/fd' = minambient
5125                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5126                                                                 //   ...
5127                                                                 //   fa' = fd' * minambient
5128                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5129                                                                 //   ...
5130                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5131                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5132                                                                 //   ...
5133                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5134                                                                 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
5135                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5136                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5137                                                         }
5138                                                 }
5139                                         }
5140
5141                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5142                                         {
5143                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5144                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5145                                                 f = fa + 0.25 * fd;
5146                                                 if(f > 0)
5147                                                 {
5148                                                         // adjust brightness and saturation to target
5149                                                         avg[0] = avg[1] = avg[2] = fa / f;
5150                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5151                                                         avg[0] = avg[1] = avg[2] = fd / f;
5152                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5153                                                 }
5154                                         }
5155                                 }
5156                         }
5157                         else // highly rare
5158                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5159                 }
5160
5161                 // move the light direction into modelspace coordinates for lighting code
5162                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5163                 if(VectorLength2(ent->modellight_lightdir) == 0)
5164                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5165                 VectorNormalize(ent->modellight_lightdir);
5166         }
5167 }
5168
5169 #define MAX_LINEOFSIGHTTRACES 64
5170
5171 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5172 {
5173         int i;
5174         vec3_t boxmins, boxmaxs;
5175         vec3_t start;
5176         vec3_t end;
5177         dp_model_t *model = r_refdef.scene.worldmodel;
5178
5179         if (!model || !model->brush.TraceLineOfSight)
5180                 return true;
5181
5182         // expand the box a little
5183         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5184         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5185         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5186         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5187         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5188         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5189
5190         // return true if eye is inside enlarged box
5191         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5192                 return true;
5193
5194         // try center
5195         VectorCopy(eye, start);
5196         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5197         if (model->brush.TraceLineOfSight(model, start, end))
5198                 return true;
5199
5200         // try various random positions
5201         for (i = 0;i < numsamples;i++)
5202         {
5203                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5204                 if (model->brush.TraceLineOfSight(model, start, end))
5205                         return true;
5206         }
5207
5208         return false;
5209 }
5210
5211
5212 static void R_View_UpdateEntityVisible (void)
5213 {
5214         int i;
5215         int renderimask;
5216         int samples;
5217         entity_render_t *ent;
5218
5219         if (r_refdef.envmap || r_fb.water.hideplayer)
5220                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5221         else if (chase_active.integer || r_fb.water.renderingscene)
5222                 renderimask = RENDER_VIEWMODEL;
5223         else
5224                 renderimask = RENDER_EXTERIORMODEL;
5225         if (!r_drawviewmodel.integer)
5226                 renderimask |= RENDER_VIEWMODEL;
5227         if (!r_drawexteriormodel.integer)
5228                 renderimask |= RENDER_EXTERIORMODEL;
5229         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5230         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5231         {
5232                 // worldmodel can check visibility
5233                 for (i = 0;i < r_refdef.scene.numentities;i++)
5234                 {
5235                         ent = r_refdef.scene.entities[i];
5236                         if (!(ent->flags & renderimask))
5237                         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)))
5238                         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))
5239                                 r_refdef.viewcache.entityvisible[i] = true;
5240                 }
5241         }
5242         else
5243         {
5244                 // no worldmodel or it can't check visibility
5245                 for (i = 0;i < r_refdef.scene.numentities;i++)
5246                 {
5247                         ent = r_refdef.scene.entities[i];
5248                         if (!(ent->flags & renderimask))
5249                         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)))
5250                                 r_refdef.viewcache.entityvisible[i] = true;
5251                 }
5252         }
5253         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5254                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5255         {
5256                 for (i = 0;i < r_refdef.scene.numentities;i++)
5257                 {
5258                         if (!r_refdef.viewcache.entityvisible[i])
5259                                 continue;
5260                         ent = r_refdef.scene.entities[i];
5261                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5262                         {
5263                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5264                                 if (samples < 0)
5265                                         continue; // temp entities do pvs only
5266                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5267                                         ent->last_trace_visibility = realtime;
5268                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5269                                         r_refdef.viewcache.entityvisible[i] = 0;
5270                         }
5271                 }
5272         }
5273 }
5274
5275 /// only used if skyrendermasked, and normally returns false
5276 static int R_DrawBrushModelsSky (void)
5277 {
5278         int i, sky;
5279         entity_render_t *ent;
5280
5281         sky = false;
5282         for (i = 0;i < r_refdef.scene.numentities;i++)
5283         {
5284                 if (!r_refdef.viewcache.entityvisible[i])
5285                         continue;
5286                 ent = r_refdef.scene.entities[i];
5287                 if (!ent->model || !ent->model->DrawSky)
5288                         continue;
5289                 ent->model->DrawSky(ent);
5290                 sky = true;
5291         }
5292         return sky;
5293 }
5294
5295 static void R_DrawNoModel(entity_render_t *ent);
5296 static void R_DrawModels(void)
5297 {
5298         int i;
5299         entity_render_t *ent;
5300
5301         for (i = 0;i < r_refdef.scene.numentities;i++)
5302         {
5303                 if (!r_refdef.viewcache.entityvisible[i])
5304                         continue;
5305                 ent = r_refdef.scene.entities[i];
5306                 r_refdef.stats[r_stat_entities]++;
5307                 /*
5308                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5309                 {
5310                         vec3_t f, l, u, o;
5311                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5312                         Con_Printf("R_DrawModels\n");
5313                         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]);
5314                         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);
5315                         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);
5316                 }
5317                 */
5318                 if (ent->model && ent->model->Draw != NULL)
5319                         ent->model->Draw(ent);
5320                 else
5321                         R_DrawNoModel(ent);
5322         }
5323 }
5324
5325 static void R_DrawModelsDepth(void)
5326 {
5327         int i;
5328         entity_render_t *ent;
5329
5330         for (i = 0;i < r_refdef.scene.numentities;i++)
5331         {
5332                 if (!r_refdef.viewcache.entityvisible[i])
5333                         continue;
5334                 ent = r_refdef.scene.entities[i];
5335                 if (ent->model && ent->model->DrawDepth != NULL)
5336                         ent->model->DrawDepth(ent);
5337         }
5338 }
5339
5340 static void R_DrawModelsDebug(void)
5341 {
5342         int i;
5343         entity_render_t *ent;
5344
5345         for (i = 0;i < r_refdef.scene.numentities;i++)
5346         {
5347                 if (!r_refdef.viewcache.entityvisible[i])
5348                         continue;
5349                 ent = r_refdef.scene.entities[i];
5350                 if (ent->model && ent->model->DrawDebug != NULL)
5351                         ent->model->DrawDebug(ent);
5352         }
5353 }
5354
5355 static void R_DrawModelsAddWaterPlanes(void)
5356 {
5357         int i;
5358         entity_render_t *ent;
5359
5360         for (i = 0;i < r_refdef.scene.numentities;i++)
5361         {
5362                 if (!r_refdef.viewcache.entityvisible[i])
5363                         continue;
5364                 ent = r_refdef.scene.entities[i];
5365                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5366                         ent->model->DrawAddWaterPlanes(ent);
5367         }
5368 }
5369
5370 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}};
5371
5372 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5373 {
5374         if (r_hdr_irisadaptation.integer)
5375         {
5376                 vec3_t p;
5377                 vec3_t ambient;
5378                 vec3_t diffuse;
5379                 vec3_t diffusenormal;
5380                 vec3_t forward;
5381                 vec_t brightness = 0.0f;
5382                 vec_t goal;
5383                 vec_t current;
5384                 vec_t d;
5385                 int c;
5386                 VectorCopy(r_refdef.view.forward, forward);
5387                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5388                 {
5389                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5390                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5391                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5392                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5393                         d = DotProduct(forward, diffusenormal);
5394                         brightness += VectorLength(ambient);
5395                         if (d > 0)
5396                                 brightness += d * VectorLength(diffuse);
5397                 }
5398                 brightness *= 1.0f / c;
5399                 brightness += 0.00001f; // make sure it's never zero
5400                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5401                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5402                 current = r_hdr_irisadaptation_value.value;
5403                 if (current < goal)
5404                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5405                 else if (current > goal)
5406                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5407                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5408                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5409         }
5410         else if (r_hdr_irisadaptation_value.value != 1.0f)
5411                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5412 }
5413
5414 static void R_View_SetFrustum(const int *scissor)
5415 {
5416         int i;
5417         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5418         vec3_t forward, left, up, origin, v;
5419
5420         if(scissor)
5421         {
5422                 // flipped x coordinates (because x points left here)
5423                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5424                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5425
5426                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5427                 switch(vid.renderpath)
5428                 {
5429                         case RENDERPATH_D3D9:
5430                         case RENDERPATH_D3D10:
5431                         case RENDERPATH_D3D11:
5432                                 // non-flipped y coordinates
5433                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5434                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5435                                 break;
5436                         case RENDERPATH_SOFT:
5437                         case RENDERPATH_GL11:
5438                         case RENDERPATH_GL13:
5439                         case RENDERPATH_GL20:
5440                         case RENDERPATH_GLES1:
5441                         case RENDERPATH_GLES2:
5442                                 // non-flipped y coordinates
5443                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5444                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5445                                 break;
5446                 }
5447         }
5448
5449         // we can't trust r_refdef.view.forward and friends in reflected scenes
5450         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5451
5452 #if 0
5453         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5454         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5455         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5456         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5457         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5458         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5459         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5460         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5461         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5462         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5463         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5464         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5465 #endif
5466
5467 #if 0
5468         zNear = r_refdef.nearclip;
5469         nudge = 1.0 - 1.0 / (1<<23);
5470         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5471         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5472         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5473         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5474         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5475         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5476         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5477         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5478 #endif
5479
5480
5481
5482 #if 0
5483         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5484         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5485         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5486         r_refdef.view.frustum[0].dist = m[15] - m[12];
5487
5488         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5489         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5490         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5491         r_refdef.view.frustum[1].dist = m[15] + m[12];
5492
5493         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5494         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5495         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5496         r_refdef.view.frustum[2].dist = m[15] - m[13];
5497
5498         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5499         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5500         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5501         r_refdef.view.frustum[3].dist = m[15] + m[13];
5502
5503         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5504         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5505         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5506         r_refdef.view.frustum[4].dist = m[15] - m[14];
5507
5508         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5509         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5510         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5511         r_refdef.view.frustum[5].dist = m[15] + m[14];
5512 #endif
5513
5514         if (r_refdef.view.useperspective)
5515         {
5516                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5517                 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]);
5518                 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]);
5519                 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]);
5520                 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]);
5521
5522                 // then the normals from the corners relative to origin
5523                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5524                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5525                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5526                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5527
5528                 // in a NORMAL view, forward cross left == up
5529                 // in a REFLECTED view, forward cross left == down
5530                 // so our cross products above need to be adjusted for a left handed coordinate system
5531                 CrossProduct(forward, left, v);
5532                 if(DotProduct(v, up) < 0)
5533                 {
5534                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5535                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5536                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5537                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5538                 }
5539
5540                 // Leaving those out was a mistake, those were in the old code, and they
5541                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5542                 // I couldn't reproduce it after adding those normalizations. --blub
5543                 VectorNormalize(r_refdef.view.frustum[0].normal);
5544                 VectorNormalize(r_refdef.view.frustum[1].normal);
5545                 VectorNormalize(r_refdef.view.frustum[2].normal);
5546                 VectorNormalize(r_refdef.view.frustum[3].normal);
5547
5548                 // make the corners absolute
5549                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5550                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5551                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5552                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5553
5554                 // one more normal
5555                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5556
5557                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5558                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5559                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5560                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5561                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5562         }
5563         else
5564         {
5565                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5566                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5567                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5568                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5569                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5570                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5571                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5572                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5573                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5574                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5575         }
5576         r_refdef.view.numfrustumplanes = 5;
5577
5578         if (r_refdef.view.useclipplane)
5579         {
5580                 r_refdef.view.numfrustumplanes = 6;
5581                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5582         }
5583
5584         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5585                 PlaneClassify(r_refdef.view.frustum + i);
5586
5587         // LordHavoc: note to all quake engine coders, Quake had a special case
5588         // for 90 degrees which assumed a square view (wrong), so I removed it,
5589         // Quake2 has it disabled as well.
5590
5591         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5592         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5593         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5594         //PlaneClassify(&frustum[0]);
5595
5596         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5597         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5598         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5599         //PlaneClassify(&frustum[1]);
5600
5601         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5602         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5603         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5604         //PlaneClassify(&frustum[2]);
5605
5606         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5607         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5608         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5609         //PlaneClassify(&frustum[3]);
5610
5611         // nearclip plane
5612         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5613         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5614         //PlaneClassify(&frustum[4]);
5615 }
5616
5617 static void R_View_UpdateWithScissor(const int *myscissor)
5618 {
5619         R_Main_ResizeViewCache();
5620         R_View_SetFrustum(myscissor);
5621         R_View_WorldVisibility(r_refdef.view.useclipplane);
5622         R_View_UpdateEntityVisible();
5623         R_View_UpdateEntityLighting();
5624 }
5625
5626 static void R_View_Update(void)
5627 {
5628         R_Main_ResizeViewCache();
5629         R_View_SetFrustum(NULL);
5630         R_View_WorldVisibility(r_refdef.view.useclipplane);
5631         R_View_UpdateEntityVisible();
5632         R_View_UpdateEntityLighting();
5633 }
5634
5635 float viewscalefpsadjusted = 1.0f;
5636
5637 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5638 {
5639         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5640         scale = bound(0.03125f, scale, 1.0f);
5641         *outwidth = (int)ceil(width * scale);
5642         *outheight = (int)ceil(height * scale);
5643 }
5644
5645 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5646 {
5647         const float *customclipplane = NULL;
5648         float plane[4];
5649         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5650         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5651         {
5652                 // LordHavoc: couldn't figure out how to make this approach the
5653                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5654                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5655                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5656                         dist = r_refdef.view.clipplane.dist;
5657                 plane[0] = r_refdef.view.clipplane.normal[0];
5658                 plane[1] = r_refdef.view.clipplane.normal[1];
5659                 plane[2] = r_refdef.view.clipplane.normal[2];
5660                 plane[3] = -dist;
5661                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5662         }
5663
5664         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5665         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5666
5667         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5668         if (!r_refdef.view.useperspective)
5669                 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);
5670         else if (vid.stencil && r_useinfinitefarclip.integer)
5671                 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);
5672         else
5673                 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);
5674         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5675         R_SetViewport(&r_refdef.view.viewport);
5676         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5677         {
5678                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5679                 float screenplane[4];
5680                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5681                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5682                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5683                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5684                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5685         }
5686 }
5687
5688 void R_EntityMatrix(const matrix4x4_t *matrix)
5689 {
5690         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5691         {
5692                 gl_modelmatrixchanged = false;
5693                 gl_modelmatrix = *matrix;
5694                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5695                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5696                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5697                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5698                 CHECKGLERROR
5699                 switch(vid.renderpath)
5700                 {
5701                 case RENDERPATH_D3D9:
5702 #ifdef SUPPORTD3D
5703                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5704                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5705 #endif
5706                         break;
5707                 case RENDERPATH_D3D10:
5708                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5709                         break;
5710                 case RENDERPATH_D3D11:
5711                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5712                         break;
5713                 case RENDERPATH_GL11:
5714                 case RENDERPATH_GL13:
5715                 case RENDERPATH_GLES1:
5716 #ifndef USE_GLES2
5717                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5718 #endif
5719                         break;
5720                 case RENDERPATH_SOFT:
5721                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5722                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5723                         break;
5724                 case RENDERPATH_GL20:
5725                 case RENDERPATH_GLES2:
5726                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5727                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5728                         break;
5729                 }
5730         }
5731 }
5732
5733 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5734 {
5735         r_viewport_t viewport;
5736
5737         CHECKGLERROR
5738
5739         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5740         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);
5741         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5742         R_SetViewport(&viewport);
5743         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5744         GL_Color(1, 1, 1, 1);
5745         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5746         GL_BlendFunc(GL_ONE, GL_ZERO);
5747         GL_ScissorTest(false);
5748         GL_DepthMask(false);
5749         GL_DepthRange(0, 1);
5750         GL_DepthTest(false);
5751         GL_DepthFunc(GL_LEQUAL);
5752         R_EntityMatrix(&identitymatrix);
5753         R_Mesh_ResetTextureState();
5754         GL_PolygonOffset(0, 0);
5755         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5756         switch(vid.renderpath)
5757         {
5758         case RENDERPATH_GL11:
5759         case RENDERPATH_GL13:
5760         case RENDERPATH_GL20:
5761         case RENDERPATH_GLES1:
5762         case RENDERPATH_GLES2:
5763                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5764                 break;
5765         case RENDERPATH_D3D9:
5766         case RENDERPATH_D3D10:
5767         case RENDERPATH_D3D11:
5768         case RENDERPATH_SOFT:
5769                 break;
5770         }
5771         GL_CullFace(GL_NONE);
5772
5773         CHECKGLERROR
5774 }
5775
5776 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5777 {
5778         DrawQ_Finish();
5779
5780         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5781 }
5782
5783 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5784 {
5785         DrawQ_Finish();
5786
5787         R_SetupView(true, fbo, depthtexture, colortexture);
5788         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5789         GL_Color(1, 1, 1, 1);
5790         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5791         GL_BlendFunc(GL_ONE, GL_ZERO);
5792         GL_ScissorTest(true);
5793         GL_DepthMask(true);
5794         GL_DepthRange(0, 1);
5795         GL_DepthTest(true);
5796         GL_DepthFunc(GL_LEQUAL);
5797         R_EntityMatrix(&identitymatrix);
5798         R_Mesh_ResetTextureState();
5799         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5800         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5801         switch(vid.renderpath)
5802         {
5803         case RENDERPATH_GL11:
5804         case RENDERPATH_GL13:
5805         case RENDERPATH_GL20:
5806         case RENDERPATH_GLES1:
5807         case RENDERPATH_GLES2:
5808                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5809                 break;
5810         case RENDERPATH_D3D9:
5811         case RENDERPATH_D3D10:
5812         case RENDERPATH_D3D11:
5813         case RENDERPATH_SOFT:
5814                 break;
5815         }
5816         GL_CullFace(r_refdef.view.cullface_back);
5817 }
5818
5819 /*
5820 ================
5821 R_RenderView_UpdateViewVectors
5822 ================
5823 */
5824 void R_RenderView_UpdateViewVectors(void)
5825 {
5826         // break apart the view matrix into vectors for various purposes
5827         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5828         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5829         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5830         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5831         // make an inverted copy of the view matrix for tracking sprites
5832         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5833 }
5834
5835 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5836 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5837
5838 static void R_Water_StartFrame(void)
5839 {
5840         int i;
5841         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5842         r_waterstate_waterplane_t *p;
5843         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;
5844
5845         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5846                 return;
5847
5848         switch(vid.renderpath)
5849         {
5850         case RENDERPATH_GL20:
5851         case RENDERPATH_D3D9:
5852         case RENDERPATH_D3D10:
5853         case RENDERPATH_D3D11:
5854         case RENDERPATH_SOFT:
5855         case RENDERPATH_GLES2:
5856                 break;
5857         case RENDERPATH_GL11:
5858         case RENDERPATH_GL13:
5859         case RENDERPATH_GLES1:
5860                 return;
5861         }
5862
5863         // set waterwidth and waterheight to the water resolution that will be
5864         // used (often less than the screen resolution for faster rendering)
5865         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5866
5867         // calculate desired texture sizes
5868         // can't use water if the card does not support the texture size
5869         if (!r_water.integer || r_showsurfaces.integer)
5870                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5871         else if (vid.support.arb_texture_non_power_of_two)
5872         {
5873                 texturewidth = waterwidth;
5874                 textureheight = waterheight;
5875                 camerawidth = waterwidth;
5876                 cameraheight = waterheight;
5877         }
5878         else
5879         {
5880                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5881                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5882                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5883                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5884         }
5885
5886         // allocate textures as needed
5887         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))
5888         {
5889                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5890                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5891                 {
5892                         if (p->texture_refraction)
5893                                 R_FreeTexture(p->texture_refraction);
5894                         p->texture_refraction = NULL;
5895                         if (p->fbo_refraction)
5896                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5897                         p->fbo_refraction = 0;
5898                         if (p->texture_reflection)
5899                                 R_FreeTexture(p->texture_reflection);
5900                         p->texture_reflection = NULL;
5901                         if (p->fbo_reflection)
5902                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5903                         p->fbo_reflection = 0;
5904                         if (p->texture_camera)
5905                                 R_FreeTexture(p->texture_camera);
5906                         p->texture_camera = NULL;
5907                         if (p->fbo_camera)
5908                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5909                         p->fbo_camera = 0;
5910                 }
5911                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5912                 r_fb.water.texturewidth = texturewidth;
5913                 r_fb.water.textureheight = textureheight;
5914                 r_fb.water.camerawidth = camerawidth;
5915                 r_fb.water.cameraheight = cameraheight;
5916         }
5917
5918         if (r_fb.water.texturewidth)
5919         {
5920                 int scaledwidth, scaledheight;
5921
5922                 r_fb.water.enabled = true;
5923
5924                 // water resolution is usually reduced
5925                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5926                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5927                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5928
5929                 // set up variables that will be used in shader setup
5930                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5931                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5932                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5933                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5934         }
5935
5936         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5937         r_fb.water.numwaterplanes = 0;
5938 }
5939
5940 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5941 {
5942         int planeindex, bestplaneindex, vertexindex;
5943         vec3_t mins, maxs, normal, center, v, n;
5944         vec_t planescore, bestplanescore;
5945         mplane_t plane;
5946         r_waterstate_waterplane_t *p;
5947         texture_t *t = R_GetCurrentTexture(surface->texture);
5948
5949         rsurface.texture = t;
5950         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5951         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5952         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5953                 return;
5954         // average the vertex normals, find the surface bounds (after deformvertexes)
5955         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5956         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5957         VectorCopy(n, normal);
5958         VectorCopy(v, mins);
5959         VectorCopy(v, maxs);
5960         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5961         {
5962                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5963                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5964                 VectorAdd(normal, n, normal);
5965                 mins[0] = min(mins[0], v[0]);
5966                 mins[1] = min(mins[1], v[1]);
5967                 mins[2] = min(mins[2], v[2]);
5968                 maxs[0] = max(maxs[0], v[0]);
5969                 maxs[1] = max(maxs[1], v[1]);
5970                 maxs[2] = max(maxs[2], v[2]);
5971         }
5972         VectorNormalize(normal);
5973         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5974
5975         VectorCopy(normal, plane.normal);
5976         VectorNormalize(plane.normal);
5977         plane.dist = DotProduct(center, plane.normal);
5978         PlaneClassify(&plane);
5979         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5980         {
5981                 // skip backfaces (except if nocullface is set)
5982 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5983 //                      return;
5984                 VectorNegate(plane.normal, plane.normal);
5985                 plane.dist *= -1;
5986                 PlaneClassify(&plane);
5987         }
5988
5989
5990         // find a matching plane if there is one
5991         bestplaneindex = -1;
5992         bestplanescore = 1048576.0f;
5993         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5994         {
5995                 if(p->camera_entity == t->camera_entity)
5996                 {
5997                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5998                         if (bestplaneindex < 0 || bestplanescore > planescore)
5999                         {
6000                                 bestplaneindex = planeindex;
6001                                 bestplanescore = planescore;
6002                         }
6003                 }
6004         }
6005         planeindex = bestplaneindex;
6006
6007         // if this surface does not fit any known plane rendered this frame, add one
6008         if (planeindex < 0 || bestplanescore > 0.001f)
6009         {
6010                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6011                 {
6012                         // store the new plane
6013                         planeindex = r_fb.water.numwaterplanes++;
6014                         p = r_fb.water.waterplanes + planeindex;
6015                         p->plane = plane;
6016                         // clear materialflags and pvs
6017                         p->materialflags = 0;
6018                         p->pvsvalid = false;
6019                         p->camera_entity = t->camera_entity;
6020                         VectorCopy(mins, p->mins);
6021                         VectorCopy(maxs, p->maxs);
6022                 }
6023                 else
6024                 {
6025                         // We're totally screwed.
6026                         return;
6027                 }
6028         }
6029         else
6030         {
6031                 // merge mins/maxs when we're adding this surface to the plane
6032                 p = r_fb.water.waterplanes + planeindex;
6033                 p->mins[0] = min(p->mins[0], mins[0]);
6034                 p->mins[1] = min(p->mins[1], mins[1]);
6035                 p->mins[2] = min(p->mins[2], mins[2]);
6036                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6037                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6038                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6039         }
6040         // merge this surface's materialflags into the waterplane
6041         p->materialflags |= t->currentmaterialflags;
6042         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6043         {
6044                 // merge this surface's PVS into the waterplane
6045                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6046                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6047                 {
6048                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6049                         p->pvsvalid = true;
6050                 }
6051         }
6052 }
6053
6054 extern cvar_t r_drawparticles;
6055 extern cvar_t r_drawdecals;
6056
6057 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6058 {
6059         int myscissor[4];
6060         r_refdef_view_t originalview;
6061         r_refdef_view_t myview;
6062         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;
6063         r_waterstate_waterplane_t *p;
6064         vec3_t visorigin;
6065         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;
6066         char vabuf[1024];
6067
6068         originalview = r_refdef.view;
6069
6070         // lowquality hack, temporarily shut down some cvars and restore afterwards
6071         qualityreduction = r_water_lowquality.integer;
6072         if (qualityreduction > 0)
6073         {
6074                 if (qualityreduction >= 1)
6075                 {
6076                         old_r_shadows = r_shadows.integer;
6077                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6078                         old_r_dlight = r_shadow_realtime_dlight.integer;
6079                         Cvar_SetValueQuick(&r_shadows, 0);
6080                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6081                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6082                 }
6083                 if (qualityreduction >= 2)
6084                 {
6085                         old_r_dynamic = r_dynamic.integer;
6086                         old_r_particles = r_drawparticles.integer;
6087                         old_r_decals = r_drawdecals.integer;
6088                         Cvar_SetValueQuick(&r_dynamic, 0);
6089                         Cvar_SetValueQuick(&r_drawparticles, 0);
6090                         Cvar_SetValueQuick(&r_drawdecals, 0);
6091                 }
6092         }
6093
6094         // make sure enough textures are allocated
6095         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6096         {
6097                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6098                         continue;
6099                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6100                 {
6101                         if (!p->texture_refraction)
6102                                 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);
6103                         if (!p->texture_refraction)
6104                                 goto error;
6105                         if (usewaterfbo)
6106                         {
6107                                 if (r_fb.water.depthtexture == NULL)
6108                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6109                                 if (p->fbo_refraction == 0)
6110                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6111                         }
6112                 }
6113                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6114                 {
6115                         if (!p->texture_camera)
6116                                 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);
6117                         if (!p->texture_camera)
6118                                 goto error;
6119                         if (usewaterfbo)
6120                         {
6121                                 if (r_fb.water.depthtexture == NULL)
6122                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6123                                 if (p->fbo_camera == 0)
6124                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6125                         }
6126                 }
6127
6128                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6129                 {
6130                         if (!p->texture_reflection)
6131                                 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);
6132                         if (!p->texture_reflection)
6133                                 goto error;
6134                         if (usewaterfbo)
6135                         {
6136                                 if (r_fb.water.depthtexture == NULL)
6137                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6138                                 if (p->fbo_reflection == 0)
6139                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6140                         }
6141                 }
6142         }
6143
6144         // render views
6145         r_refdef.view = originalview;
6146         r_refdef.view.showdebug = false;
6147         r_refdef.view.width = r_fb.water.waterwidth;
6148         r_refdef.view.height = r_fb.water.waterheight;
6149         r_refdef.view.useclipplane = true;
6150         myview = r_refdef.view;
6151         r_fb.water.renderingscene = true;
6152         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6153         {
6154                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6155                         continue;
6156                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6157                 {
6158                         r_refdef.view = myview;
6159                         if(r_water_scissormode.integer)
6160                         {
6161                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6162                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6163                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6164                         }
6165
6166                         // render reflected scene and copy into texture
6167                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6168                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6169                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6170                         r_refdef.view.clipplane = p->plane;
6171                         // reverse the cullface settings for this render
6172                         r_refdef.view.cullface_front = GL_FRONT;
6173                         r_refdef.view.cullface_back = GL_BACK;
6174                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6175                         {
6176                                 r_refdef.view.usecustompvs = true;
6177                                 if (p->pvsvalid)
6178                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6179                                 else
6180                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6181                         }
6182
6183                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6184                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6185                         R_ClearScreen(r_refdef.fogenabled);
6186                         if(r_water_scissormode.integer & 2)
6187                                 R_View_UpdateWithScissor(myscissor);
6188                         else
6189                                 R_View_Update();
6190                         R_AnimCache_CacheVisibleEntities();
6191                         if(r_water_scissormode.integer & 1)
6192                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6193                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6194
6195                         if (!p->fbo_reflection)
6196                                 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);
6197                         r_fb.water.hideplayer = false;
6198                 }
6199
6200                 // render the normal view scene and copy into texture
6201                 // (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)
6202                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6203                 {
6204                         r_refdef.view = myview;
6205                         if(r_water_scissormode.integer)
6206                         {
6207                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6208                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6209                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6210                         }
6211
6212                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6213
6214                         r_refdef.view.clipplane = p->plane;
6215                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6216                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6217
6218                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6219                         {
6220                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6221                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6222                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6223                                 R_RenderView_UpdateViewVectors();
6224                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6225                                 {
6226                                         r_refdef.view.usecustompvs = true;
6227                                         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);
6228                                 }
6229                         }
6230
6231                         PlaneClassify(&r_refdef.view.clipplane);
6232
6233                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6234                         R_ClearScreen(r_refdef.fogenabled);
6235                         if(r_water_scissormode.integer & 2)
6236                                 R_View_UpdateWithScissor(myscissor);
6237                         else
6238                                 R_View_Update();
6239                         R_AnimCache_CacheVisibleEntities();
6240                         if(r_water_scissormode.integer & 1)
6241                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6242                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6243
6244                         if (!p->fbo_refraction)
6245                                 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);
6246                         r_fb.water.hideplayer = false;
6247                 }
6248                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6249                 {
6250                         r_refdef.view = myview;
6251
6252                         r_refdef.view.clipplane = p->plane;
6253                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6254                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6255
6256                         r_refdef.view.width = r_fb.water.camerawidth;
6257                         r_refdef.view.height = r_fb.water.cameraheight;
6258                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6259                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6260                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6261                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6262
6263                         if(p->camera_entity)
6264                         {
6265                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6266                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6267                         }
6268
6269                         // note: all of the view is used for displaying... so
6270                         // there is no use in scissoring
6271
6272                         // reverse the cullface settings for this render
6273                         r_refdef.view.cullface_front = GL_FRONT;
6274                         r_refdef.view.cullface_back = GL_BACK;
6275                         // also reverse the view matrix
6276                         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
6277                         R_RenderView_UpdateViewVectors();
6278                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6279                         {
6280                                 r_refdef.view.usecustompvs = true;
6281                                 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);
6282                         }
6283                         
6284                         // camera needs no clipplane
6285                         r_refdef.view.useclipplane = false;
6286
6287                         PlaneClassify(&r_refdef.view.clipplane);
6288
6289                         r_fb.water.hideplayer = false;
6290
6291                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6292                         R_ClearScreen(r_refdef.fogenabled);
6293                         R_View_Update();
6294                         R_AnimCache_CacheVisibleEntities();
6295                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6296
6297                         if (!p->fbo_camera)
6298                                 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);
6299                         r_fb.water.hideplayer = false;
6300                 }
6301
6302         }
6303         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6304         r_fb.water.renderingscene = false;
6305         r_refdef.view = originalview;
6306         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6307         if (!r_fb.water.depthtexture)
6308                 R_ClearScreen(r_refdef.fogenabled);
6309         R_View_Update();
6310         R_AnimCache_CacheVisibleEntities();
6311         goto finish;
6312 error:
6313         r_refdef.view = originalview;
6314         r_fb.water.renderingscene = false;
6315         Cvar_SetValueQuick(&r_water, 0);
6316         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6317 finish:
6318         // lowquality hack, restore cvars
6319         if (qualityreduction > 0)
6320         {
6321                 if (qualityreduction >= 1)
6322                 {
6323                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6324                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6325                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6326                 }
6327                 if (qualityreduction >= 2)
6328                 {
6329                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6330                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6331                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6332                 }
6333         }
6334 }
6335
6336 static void R_Bloom_StartFrame(void)
6337 {
6338         int i;
6339         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6340         int viewwidth, viewheight;
6341         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6342         textype_t textype = TEXTYPE_COLORBUFFER;
6343
6344         switch (vid.renderpath)
6345         {
6346         case RENDERPATH_GL20:
6347                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6348                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6349                 {
6350                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6351                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6352                 }
6353                 break;
6354         case RENDERPATH_GL11:
6355         case RENDERPATH_GL13:
6356         case RENDERPATH_GLES1:
6357         case RENDERPATH_GLES2:
6358         case RENDERPATH_D3D9:
6359         case RENDERPATH_D3D10:
6360         case RENDERPATH_D3D11:
6361                 r_fb.usedepthtextures = false;
6362                 break;
6363         case RENDERPATH_SOFT:
6364                 r_fb.usedepthtextures = true;
6365                 break;
6366         }
6367
6368         if (r_viewscale_fpsscaling.integer)
6369         {
6370                 double actualframetime;
6371                 double targetframetime;
6372                 double adjust;
6373                 actualframetime = r_refdef.lastdrawscreentime;
6374                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6375                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6376                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6377                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6378                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6379                 viewscalefpsadjusted += adjust;
6380                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6381         }
6382         else
6383                 viewscalefpsadjusted = 1.0f;
6384
6385         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6386
6387         switch(vid.renderpath)
6388         {
6389         case RENDERPATH_GL20:
6390         case RENDERPATH_D3D9:
6391         case RENDERPATH_D3D10:
6392         case RENDERPATH_D3D11:
6393         case RENDERPATH_SOFT:
6394         case RENDERPATH_GLES2:
6395                 break;
6396         case RENDERPATH_GL11:
6397         case RENDERPATH_GL13:
6398         case RENDERPATH_GLES1:
6399                 return;
6400         }
6401
6402         // set bloomwidth and bloomheight to the bloom resolution that will be
6403         // used (often less than the screen resolution for faster rendering)
6404         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6405         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6406         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6407         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6408         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6409
6410         // calculate desired texture sizes
6411         if (vid.support.arb_texture_non_power_of_two)
6412         {
6413                 screentexturewidth = vid.width;
6414                 screentextureheight = vid.height;
6415                 bloomtexturewidth = r_fb.bloomwidth;
6416                 bloomtextureheight = r_fb.bloomheight;
6417         }
6418         else
6419         {
6420                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6421                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6422                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6423                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6424         }
6425
6426         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))
6427         {
6428                 Cvar_SetValueQuick(&r_bloom, 0);
6429                 Cvar_SetValueQuick(&r_motionblur, 0);
6430                 Cvar_SetValueQuick(&r_damageblur, 0);
6431         }
6432
6433         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6434          && !r_bloom.integer
6435          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6436          && !useviewfbo
6437          && r_viewscale.value == 1.0f
6438          && !r_viewscale_fpsscaling.integer)
6439                 screentexturewidth = screentextureheight = 0;
6440         if (!r_bloom.integer)
6441                 bloomtexturewidth = bloomtextureheight = 0;
6442
6443         // allocate textures as needed
6444         if (r_fb.screentexturewidth != screentexturewidth
6445          || r_fb.screentextureheight != screentextureheight
6446          || r_fb.bloomtexturewidth != bloomtexturewidth
6447          || r_fb.bloomtextureheight != bloomtextureheight
6448          || r_fb.textype != textype
6449          || useviewfbo != (r_fb.fbo != 0))
6450         {
6451                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6452                 {
6453                         if (r_fb.bloomtexture[i])
6454                                 R_FreeTexture(r_fb.bloomtexture[i]);
6455                         r_fb.bloomtexture[i] = NULL;
6456
6457                         if (r_fb.bloomfbo[i])
6458                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6459                         r_fb.bloomfbo[i] = 0;
6460                 }
6461
6462                 if (r_fb.fbo)
6463                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6464                 r_fb.fbo = 0;
6465
6466                 if (r_fb.colortexture)
6467                         R_FreeTexture(r_fb.colortexture);
6468                 r_fb.colortexture = NULL;
6469
6470                 if (r_fb.depthtexture)
6471                         R_FreeTexture(r_fb.depthtexture);
6472                 r_fb.depthtexture = NULL;
6473
6474                 if (r_fb.ghosttexture)
6475                         R_FreeTexture(r_fb.ghosttexture);
6476                 r_fb.ghosttexture = NULL;
6477
6478                 r_fb.screentexturewidth = screentexturewidth;
6479                 r_fb.screentextureheight = screentextureheight;
6480                 r_fb.bloomtexturewidth = bloomtexturewidth;
6481                 r_fb.bloomtextureheight = bloomtextureheight;
6482                 r_fb.textype = textype;
6483
6484                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6485                 {
6486                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6487                                 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);
6488                         r_fb.ghosttexture_valid = false;
6489                         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);
6490                         if (useviewfbo)
6491                         {
6492                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6493                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6494                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6495                         }
6496                 }
6497
6498                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6499                 {
6500                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6501                         {
6502                                 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);
6503                                 if (useviewfbo)
6504                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6505                         }
6506                 }
6507         }
6508
6509         // bloom texture is a different resolution
6510         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6511         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6512         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6513         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6514         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6515
6516         // set up a texcoord array for the full resolution screen image
6517         // (we have to keep this around to copy back during final render)
6518         r_fb.screentexcoord2f[0] = 0;
6519         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6520         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6521         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6522         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6523         r_fb.screentexcoord2f[5] = 0;
6524         r_fb.screentexcoord2f[6] = 0;
6525         r_fb.screentexcoord2f[7] = 0;
6526
6527         if(r_fb.fbo) 
6528         {
6529                 for (i = 1;i < 8;i += 2)
6530                 {
6531                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6532                 }
6533         }
6534
6535         // set up a texcoord array for the reduced resolution bloom image
6536         // (which will be additive blended over the screen image)
6537         r_fb.bloomtexcoord2f[0] = 0;
6538         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6539         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6540         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6541         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6542         r_fb.bloomtexcoord2f[5] = 0;
6543         r_fb.bloomtexcoord2f[6] = 0;
6544         r_fb.bloomtexcoord2f[7] = 0;
6545
6546         switch(vid.renderpath)
6547         {
6548         case RENDERPATH_GL11:
6549         case RENDERPATH_GL13:
6550         case RENDERPATH_GL20:
6551         case RENDERPATH_SOFT:
6552         case RENDERPATH_GLES1:
6553         case RENDERPATH_GLES2:
6554                 break;
6555         case RENDERPATH_D3D9:
6556         case RENDERPATH_D3D10:
6557         case RENDERPATH_D3D11:
6558                 for (i = 0;i < 4;i++)
6559                 {
6560                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6561                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6562                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6563                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6564                 }
6565                 break;
6566         }
6567
6568         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6569
6570         if (r_fb.fbo)
6571                 r_refdef.view.clear = true;
6572 }
6573
6574 static void R_Bloom_MakeTexture(void)
6575 {
6576         int x, range, dir;
6577         float xoffset, yoffset, r, brighten;
6578         rtexture_t *intex;
6579         float colorscale = r_bloom_colorscale.value;
6580
6581         r_refdef.stats[r_stat_bloom]++;
6582     
6583 #if 0
6584     // this copy is unnecessary since it happens in R_BlendView already
6585         if (!r_fb.fbo)
6586         {
6587                 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);
6588                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6589         }
6590 #endif
6591
6592         // scale down screen texture to the bloom texture size
6593         CHECKGLERROR
6594         r_fb.bloomindex = 0;
6595         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6596         R_SetViewport(&r_fb.bloomviewport);
6597         GL_DepthTest(false);
6598         GL_BlendFunc(GL_ONE, GL_ZERO);
6599         GL_Color(colorscale, colorscale, colorscale, 1);
6600         // 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...
6601         switch(vid.renderpath)
6602         {
6603         case RENDERPATH_GL11:
6604         case RENDERPATH_GL13:
6605         case RENDERPATH_GL20:
6606         case RENDERPATH_GLES1:
6607         case RENDERPATH_GLES2:
6608         case RENDERPATH_SOFT:
6609                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6610                 break;
6611         case RENDERPATH_D3D9:
6612         case RENDERPATH_D3D10:
6613         case RENDERPATH_D3D11:
6614                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6615                 break;
6616         }
6617         // TODO: do boxfilter scale-down in shader?
6618         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6619         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6620         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6621
6622         // we now have a properly scaled bloom image
6623         if (!r_fb.bloomfbo[r_fb.bloomindex])
6624         {
6625                 // copy it into the bloom texture
6626                 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);
6627                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6628         }
6629
6630         // multiply bloom image by itself as many times as desired
6631         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6632         {
6633                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6634                 r_fb.bloomindex ^= 1;
6635                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6636                 x *= 2;
6637                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6638                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6639                 {
6640                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6641                         GL_Color(r,r,r,1); // apply fix factor
6642                 }
6643                 else
6644                 {
6645                         if(x <= 2)
6646                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6647                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6648                         GL_Color(1,1,1,1); // no fix factor supported here
6649                 }
6650                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6651                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6652                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6653                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6654
6655                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6656                 {
6657                         // copy the darkened image to a texture
6658                         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);
6659                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6660                 }
6661         }
6662
6663         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6664         brighten = r_bloom_brighten.value;
6665         brighten = sqrt(brighten);
6666         if(range >= 1)
6667                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6668
6669         for (dir = 0;dir < 2;dir++)
6670         {
6671                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6672                 r_fb.bloomindex ^= 1;
6673                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6674                 // blend on at multiple vertical offsets to achieve a vertical blur
6675                 // TODO: do offset blends using GLSL
6676                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6677                 GL_BlendFunc(GL_ONE, GL_ZERO);
6678                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6679                 for (x = -range;x <= range;x++)
6680                 {
6681                         if (!dir){xoffset = 0;yoffset = x;}
6682                         else {xoffset = x;yoffset = 0;}
6683                         xoffset /= (float)r_fb.bloomtexturewidth;
6684                         yoffset /= (float)r_fb.bloomtextureheight;
6685                         // compute a texcoord array with the specified x and y offset
6686                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6687                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6688                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6689                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6690                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6691                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6692                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6693                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6694                         // this r value looks like a 'dot' particle, fading sharply to
6695                         // black at the edges
6696                         // (probably not realistic but looks good enough)
6697                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6698                         //r = brighten/(range*2+1);
6699                         r = brighten / (range * 2 + 1);
6700                         if(range >= 1)
6701                                 r *= (1 - x*x/(float)(range*range));
6702                         GL_Color(r, r, r, 1);
6703                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6704                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6705                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6706                         GL_BlendFunc(GL_ONE, GL_ONE);
6707                 }
6708
6709                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6710                 {
6711                         // copy the vertically or horizontally blurred bloom view to a texture
6712                         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);
6713                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6714                 }
6715         }
6716 }
6717
6718 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6719 {
6720         unsigned int permutation;
6721         float uservecs[4][4];
6722
6723         R_EntityMatrix(&identitymatrix);
6724
6725         switch (vid.renderpath)
6726         {
6727         case RENDERPATH_GL20:
6728         case RENDERPATH_D3D9:
6729         case RENDERPATH_D3D10:
6730         case RENDERPATH_D3D11:
6731         case RENDERPATH_SOFT:
6732         case RENDERPATH_GLES2:
6733                 permutation =
6734                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6735                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6736                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6737                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6738                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6739
6740                 if (r_fb.colortexture)
6741                 {
6742                         if (!r_fb.fbo)
6743                         {
6744                                 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);
6745                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6746                         }
6747
6748                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6749                         {
6750                                 // declare variables
6751                                 float blur_factor, blur_mouseaccel, blur_velocity;
6752                                 static float blur_average; 
6753                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6754
6755                                 // set a goal for the factoring
6756                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6757                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6758                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6759                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6760                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6761                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6762
6763                                 // from the goal, pick an averaged value between goal and last value
6764                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6765                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6766
6767                                 // enforce minimum amount of blur 
6768                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6769
6770                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6771
6772                                 // calculate values into a standard alpha
6773                                 cl.motionbluralpha = 1 - exp(-
6774                                                 (
6775                                                  (r_motionblur.value * blur_factor / 80)
6776                                                  +
6777                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6778                                                 )
6779                                                 /
6780                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6781                                           );
6782
6783                                 // randomization for the blur value to combat persistent ghosting
6784                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6785                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6786
6787                                 // apply the blur
6788                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6789                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6790                                 {
6791                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6792                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6793                                         switch(vid.renderpath)
6794                                         {
6795                                         case RENDERPATH_GL11:
6796                                         case RENDERPATH_GL13:
6797                                         case RENDERPATH_GL20:
6798                                         case RENDERPATH_GLES1:
6799                                         case RENDERPATH_GLES2:
6800                                         case RENDERPATH_SOFT:
6801                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6802                                                 break;
6803                                         case RENDERPATH_D3D9:
6804                                         case RENDERPATH_D3D10:
6805                                         case RENDERPATH_D3D11:
6806                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6807                                                 break;
6808                                         }
6809                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
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.viewport.width * r_refdef.view.viewport.height;
6812                                 }
6813
6814                                 // updates old view angles for next pass
6815                                 VectorCopy(cl.viewangles, blur_oldangles);
6816
6817                                 // copy view into the ghost texture
6818                                 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);
6819                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6820                                 r_fb.ghosttexture_valid = true;
6821                         }
6822                 }
6823                 else
6824                 {
6825                         // no r_fb.colortexture means we're rendering to the real fb
6826                         // we may still have to do view tint...
6827                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6828                         {
6829                                 // apply a color tint to the whole view
6830                                 R_ResetViewRendering2D(0, NULL, NULL);
6831                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6832                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6833                                 R_SetupShader_Generic_NoTexture(false, true);
6834                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6835                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6836                         }
6837                         break; // no screen processing, no bloom, skip it
6838                 }
6839
6840                 if (r_fb.bloomtexture[0])
6841                 {
6842                         // make the bloom texture
6843                         R_Bloom_MakeTexture();
6844                 }
6845
6846 #if _MSC_VER >= 1400
6847 #define sscanf sscanf_s
6848 #endif
6849                 memset(uservecs, 0, sizeof(uservecs));
6850                 if (r_glsl_postprocess_uservec1_enable.integer)
6851                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6852                 if (r_glsl_postprocess_uservec2_enable.integer)
6853                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6854                 if (r_glsl_postprocess_uservec3_enable.integer)
6855                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6856                 if (r_glsl_postprocess_uservec4_enable.integer)
6857                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6858
6859                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6860                 GL_Color(1, 1, 1, 1);
6861                 GL_BlendFunc(GL_ONE, GL_ZERO);
6862
6863                 switch(vid.renderpath)
6864                 {
6865                 case RENDERPATH_GL20:
6866                 case RENDERPATH_GLES2:
6867                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6868                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6869                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6870                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6871                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6872                         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]);
6873                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6874                         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]);
6875                         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]);
6876                         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]);
6877                         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]);
6878                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6879                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6880                         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);
6881                         break;
6882                 case RENDERPATH_D3D9:
6883 #ifdef SUPPORTD3D
6884                         // 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...
6885                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6886                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6887                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6888                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6889                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6890                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6891                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6892                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6893                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6894                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6895                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6896                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6897                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6898                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6899 #endif
6900                         break;
6901                 case RENDERPATH_D3D10:
6902                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6903                         break;
6904                 case RENDERPATH_D3D11:
6905                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6906                         break;
6907                 case RENDERPATH_SOFT:
6908                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6909                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6910                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6911                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6912                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6913                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6914                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6915                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6916                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6917                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6918                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6919                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6920                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6921                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6922                         break;
6923                 default:
6924                         break;
6925                 }
6926                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6927                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6928                 break;
6929         case RENDERPATH_GL11:
6930         case RENDERPATH_GL13:
6931         case RENDERPATH_GLES1:
6932                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6933                 {
6934                         // apply a color tint to the whole view
6935                         R_ResetViewRendering2D(0, NULL, NULL);
6936                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6937                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6938                         R_SetupShader_Generic_NoTexture(false, true);
6939                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6940                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6941                 }
6942                 break;
6943         }
6944 }
6945
6946 matrix4x4_t r_waterscrollmatrix;
6947
6948 void R_UpdateFog(void)
6949 {
6950         // Nehahra fog
6951         if (gamemode == GAME_NEHAHRA)
6952         {
6953                 if (gl_fogenable.integer)
6954                 {
6955                         r_refdef.oldgl_fogenable = true;
6956                         r_refdef.fog_density = gl_fogdensity.value;
6957                         r_refdef.fog_red = gl_fogred.value;
6958                         r_refdef.fog_green = gl_foggreen.value;
6959                         r_refdef.fog_blue = gl_fogblue.value;
6960                         r_refdef.fog_alpha = 1;
6961                         r_refdef.fog_start = 0;
6962                         r_refdef.fog_end = gl_skyclip.value;
6963                         r_refdef.fog_height = 1<<30;
6964                         r_refdef.fog_fadedepth = 128;
6965                 }
6966                 else if (r_refdef.oldgl_fogenable)
6967                 {
6968                         r_refdef.oldgl_fogenable = false;
6969                         r_refdef.fog_density = 0;
6970                         r_refdef.fog_red = 0;
6971                         r_refdef.fog_green = 0;
6972                         r_refdef.fog_blue = 0;
6973                         r_refdef.fog_alpha = 0;
6974                         r_refdef.fog_start = 0;
6975                         r_refdef.fog_end = 0;
6976                         r_refdef.fog_height = 1<<30;
6977                         r_refdef.fog_fadedepth = 128;
6978                 }
6979         }
6980
6981         // fog parms
6982         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6983         r_refdef.fog_start = max(0, r_refdef.fog_start);
6984         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6985
6986         if (r_refdef.fog_density && r_drawfog.integer)
6987         {
6988                 r_refdef.fogenabled = true;
6989                 // this is the point where the fog reaches 0.9986 alpha, which we
6990                 // consider a good enough cutoff point for the texture
6991                 // (0.9986 * 256 == 255.6)
6992                 if (r_fog_exp2.integer)
6993                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6994                 else
6995                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6996                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6997                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6998                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6999                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7000                         R_BuildFogHeightTexture();
7001                 // fog color was already set
7002                 // update the fog texture
7003                 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)
7004                         R_BuildFogTexture();
7005                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7006                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7007         }
7008         else
7009                 r_refdef.fogenabled = false;
7010
7011         // fog color
7012         if (r_refdef.fog_density)
7013         {
7014                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7015                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7016                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7017
7018                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7019                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7020                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7021                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7022
7023                 {
7024                         vec3_t fogvec;
7025                         VectorCopy(r_refdef.fogcolor, fogvec);
7026                         //   color.rgb *= ContrastBoost * SceneBrightness;
7027                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7028                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7029                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7030                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7031                 }
7032         }
7033 }
7034
7035 void R_UpdateVariables(void)
7036 {
7037         R_Textures_Frame();
7038
7039         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7040
7041         r_refdef.farclip = r_farclip_base.value;
7042         if (r_refdef.scene.worldmodel)
7043                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7044         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7045
7046         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7047                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7048         r_refdef.polygonfactor = 0;
7049         r_refdef.polygonoffset = 0;
7050         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7051         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7052
7053         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7054         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7055         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7056         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7057         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7058         if (FAKELIGHT_ENABLED)
7059         {
7060                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7061         }
7062         else if (r_refdef.scene.worldmodel)
7063         {
7064                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7065         }
7066         if (r_showsurfaces.integer)
7067         {
7068                 r_refdef.scene.rtworld = false;
7069                 r_refdef.scene.rtworldshadows = false;
7070                 r_refdef.scene.rtdlight = false;
7071                 r_refdef.scene.rtdlightshadows = false;
7072                 r_refdef.lightmapintensity = 0;
7073         }
7074
7075         r_gpuskeletal = false;
7076         switch(vid.renderpath)
7077         {
7078         case RENDERPATH_GL20:
7079                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7080         case RENDERPATH_D3D9:
7081         case RENDERPATH_D3D10:
7082         case RENDERPATH_D3D11:
7083         case RENDERPATH_SOFT:
7084         case RENDERPATH_GLES2:
7085                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7086                 {
7087                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7088                         {
7089                                 // build GLSL gamma texture
7090 #define RAMPWIDTH 256
7091                                 unsigned short ramp[RAMPWIDTH * 3];
7092                                 unsigned char rampbgr[RAMPWIDTH][4];
7093                                 int i;
7094
7095                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7096
7097                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7098                                 for(i = 0; i < RAMPWIDTH; ++i)
7099                                 {
7100                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7101                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7102                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7103                                         rampbgr[i][3] = 0;
7104                                 }
7105                                 if (r_texture_gammaramps)
7106                                 {
7107                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7108                                 }
7109                                 else
7110                                 {
7111                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7112                                 }
7113                         }
7114                 }
7115                 else
7116                 {
7117                         // remove GLSL gamma texture
7118                 }
7119                 break;
7120         case RENDERPATH_GL11:
7121         case RENDERPATH_GL13:
7122         case RENDERPATH_GLES1:
7123                 break;
7124         }
7125 }
7126
7127 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7128 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7129 /*
7130 ================
7131 R_SelectScene
7132 ================
7133 */
7134 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7135         if( scenetype != r_currentscenetype ) {
7136                 // store the old scenetype
7137                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7138                 r_currentscenetype = scenetype;
7139                 // move in the new scene
7140                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7141         }
7142 }
7143
7144 /*
7145 ================
7146 R_GetScenePointer
7147 ================
7148 */
7149 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7150 {
7151         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7152         if( scenetype == r_currentscenetype ) {
7153                 return &r_refdef.scene;
7154         } else {
7155                 return &r_scenes_store[ scenetype ];
7156         }
7157 }
7158
7159 static int R_SortEntities_Compare(const void *ap, const void *bp)
7160 {
7161         const entity_render_t *a = *(const entity_render_t **)ap;
7162         const entity_render_t *b = *(const entity_render_t **)bp;
7163
7164         // 1. compare model
7165         if(a->model < b->model)
7166                 return -1;
7167         if(a->model > b->model)
7168                 return +1;
7169
7170         // 2. compare skin
7171         // TODO possibly calculate the REAL skinnum here first using
7172         // skinscenes?
7173         if(a->skinnum < b->skinnum)
7174                 return -1;
7175         if(a->skinnum > b->skinnum)
7176                 return +1;
7177
7178         // everything we compared is equal
7179         return 0;
7180 }
7181 static void R_SortEntities(void)
7182 {
7183         // below or equal 2 ents, sorting never gains anything
7184         if(r_refdef.scene.numentities <= 2)
7185                 return;
7186         // sort
7187         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7188 }
7189
7190 /*
7191 ================
7192 R_RenderView
7193 ================
7194 */
7195 int dpsoftrast_test;
7196 extern cvar_t r_shadow_bouncegrid;
7197 void R_RenderView(void)
7198 {
7199         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7200         int fbo;
7201         rtexture_t *depthtexture;
7202         rtexture_t *colortexture;
7203
7204         dpsoftrast_test = r_test.integer;
7205
7206         if (r_timereport_active)
7207                 R_TimeReport("start");
7208         r_textureframe++; // used only by R_GetCurrentTexture
7209         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7210
7211         if(R_CompileShader_CheckStaticParms())
7212                 R_GLSL_Restart_f();
7213
7214         if (!r_drawentities.integer)
7215                 r_refdef.scene.numentities = 0;
7216         else if (r_sortentities.integer)
7217                 R_SortEntities();
7218
7219         R_AnimCache_ClearCache();
7220
7221         /* adjust for stereo display */
7222         if(R_Stereo_Active())
7223         {
7224                 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);
7225                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7226         }
7227
7228         if (r_refdef.view.isoverlay)
7229         {
7230                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7231                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7232                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7233                 R_TimeReport("depthclear");
7234
7235                 r_refdef.view.showdebug = false;
7236
7237                 r_fb.water.enabled = false;
7238                 r_fb.water.numwaterplanes = 0;
7239
7240                 R_RenderScene(0, NULL, NULL);
7241
7242                 r_refdef.view.matrix = originalmatrix;
7243
7244                 CHECKGLERROR
7245                 return;
7246         }
7247
7248         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7249         {
7250                 r_refdef.view.matrix = originalmatrix;
7251                 return;
7252         }
7253
7254         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7255
7256         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7257                 // in sRGB fallback, behave similar to true sRGB: convert this
7258                 // value from linear to sRGB
7259                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7260
7261         R_RenderView_UpdateViewVectors();
7262
7263         R_Shadow_UpdateWorldLightSelection();
7264
7265         R_Bloom_StartFrame();
7266
7267         // apply bloom brightness offset
7268         if(r_fb.bloomtexture[0])
7269                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7270
7271         R_Water_StartFrame();
7272
7273         // now we probably have an fbo to render into
7274         fbo = r_fb.fbo;
7275         depthtexture = r_fb.depthtexture;
7276         colortexture = r_fb.colortexture;
7277
7278         CHECKGLERROR
7279         if (r_timereport_active)
7280                 R_TimeReport("viewsetup");
7281
7282         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7283
7284         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7285         {
7286                 R_ClearScreen(r_refdef.fogenabled);
7287                 if (r_timereport_active)
7288                         R_TimeReport("viewclear");
7289         }
7290         r_refdef.view.clear = true;
7291
7292         r_refdef.view.showdebug = true;
7293
7294         R_View_Update();
7295         if (r_timereport_active)
7296                 R_TimeReport("visibility");
7297
7298         R_AnimCache_CacheVisibleEntities();
7299         if (r_timereport_active)
7300                 R_TimeReport("animcache");
7301
7302         R_Shadow_UpdateBounceGridTexture();
7303         if (r_timereport_active && r_shadow_bouncegrid.integer)
7304                 R_TimeReport("bouncegrid");
7305
7306         r_fb.water.numwaterplanes = 0;
7307         if (r_fb.water.enabled)
7308                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7309
7310         R_RenderScene(fbo, depthtexture, colortexture);
7311         r_fb.water.numwaterplanes = 0;
7312
7313         R_BlendView(fbo, depthtexture, colortexture);
7314         if (r_timereport_active)
7315                 R_TimeReport("blendview");
7316
7317         GL_Scissor(0, 0, vid.width, vid.height);
7318         GL_ScissorTest(false);
7319
7320         r_refdef.view.matrix = originalmatrix;
7321
7322         CHECKGLERROR
7323 }
7324
7325 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7326 {
7327         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7328         {
7329                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7330                 if (r_timereport_active)
7331                         R_TimeReport("waterworld");
7332         }
7333
7334         // don't let sound skip if going slow
7335         if (r_refdef.scene.extraupdate)
7336                 S_ExtraUpdate ();
7337
7338         R_DrawModelsAddWaterPlanes();
7339         if (r_timereport_active)
7340                 R_TimeReport("watermodels");
7341
7342         if (r_fb.water.numwaterplanes)
7343         {
7344                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7345                 if (r_timereport_active)
7346                         R_TimeReport("waterscenes");
7347         }
7348 }
7349
7350 extern cvar_t cl_locs_show;
7351 static void R_DrawLocs(void);
7352 static void R_DrawEntityBBoxes(void);
7353 static void R_DrawModelDecals(void);
7354 extern cvar_t cl_decals_newsystem;
7355 extern qboolean r_shadow_usingdeferredprepass;
7356 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7357 {
7358         qboolean shadowmapping = false;
7359
7360         if (r_timereport_active)
7361                 R_TimeReport("beginscene");
7362
7363         r_refdef.stats[r_stat_renders]++;
7364
7365         R_UpdateFog();
7366
7367         // don't let sound skip if going slow
7368         if (r_refdef.scene.extraupdate)
7369                 S_ExtraUpdate ();
7370
7371         R_MeshQueue_BeginScene();
7372
7373         R_SkyStartFrame();
7374
7375         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);
7376
7377         if (r_timereport_active)
7378                 R_TimeReport("skystartframe");
7379
7380         if (cl.csqc_vidvars.drawworld)
7381         {
7382                 // don't let sound skip if going slow
7383                 if (r_refdef.scene.extraupdate)
7384                         S_ExtraUpdate ();
7385
7386                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7387                 {
7388                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7389                         if (r_timereport_active)
7390                                 R_TimeReport("worldsky");
7391                 }
7392
7393                 if (R_DrawBrushModelsSky() && r_timereport_active)
7394                         R_TimeReport("bmodelsky");
7395
7396                 if (skyrendermasked && skyrenderlater)
7397                 {
7398                         // we have to force off the water clipping plane while rendering sky
7399                         R_SetupView(false, fbo, depthtexture, colortexture);
7400                         R_Sky();
7401                         R_SetupView(true, fbo, depthtexture, colortexture);
7402                         if (r_timereport_active)
7403                                 R_TimeReport("sky");
7404                 }
7405         }
7406
7407         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7408         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7409                 R_Shadow_PrepareModelShadows();
7410         if (r_timereport_active)
7411                 R_TimeReport("preparelights");
7412
7413         if (R_Shadow_ShadowMappingEnabled())
7414                 shadowmapping = true;
7415
7416         if (r_shadow_usingdeferredprepass)
7417                 R_Shadow_DrawPrepass();
7418
7419         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7420         {
7421                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7422                 if (r_timereport_active)
7423                         R_TimeReport("worlddepth");
7424         }
7425         if (r_depthfirst.integer >= 2)
7426         {
7427                 R_DrawModelsDepth();
7428                 if (r_timereport_active)
7429                         R_TimeReport("modeldepth");
7430         }
7431
7432         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7433         {
7434                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7435                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7436                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7437                 // don't let sound skip if going slow
7438                 if (r_refdef.scene.extraupdate)
7439                         S_ExtraUpdate ();
7440         }
7441
7442         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7443         {
7444                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7445                 if (r_timereport_active)
7446                         R_TimeReport("world");
7447         }
7448
7449         // don't let sound skip if going slow
7450         if (r_refdef.scene.extraupdate)
7451                 S_ExtraUpdate ();
7452
7453         R_DrawModels();
7454         if (r_timereport_active)
7455                 R_TimeReport("models");
7456
7457         // don't let sound skip if going slow
7458         if (r_refdef.scene.extraupdate)
7459                 S_ExtraUpdate ();
7460
7461         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7462         {
7463                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7464                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7465                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7466                 // don't let sound skip if going slow
7467                 if (r_refdef.scene.extraupdate)
7468                         S_ExtraUpdate ();
7469         }
7470
7471         if (!r_shadow_usingdeferredprepass)
7472         {
7473                 R_Shadow_DrawLights();
7474                 if (r_timereport_active)
7475                         R_TimeReport("rtlights");
7476         }
7477
7478         // don't let sound skip if going slow
7479         if (r_refdef.scene.extraupdate)
7480                 S_ExtraUpdate ();
7481
7482         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7483         {
7484                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7485                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7486                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7487                 // don't let sound skip if going slow
7488                 if (r_refdef.scene.extraupdate)
7489                         S_ExtraUpdate ();
7490         }
7491
7492         if (cl.csqc_vidvars.drawworld)
7493         {
7494                 if (cl_decals_newsystem.integer)
7495                 {
7496                         R_DrawModelDecals();
7497                         if (r_timereport_active)
7498                                 R_TimeReport("modeldecals");
7499                 }
7500                 else
7501                 {
7502                         R_DrawDecals();
7503                         if (r_timereport_active)
7504                                 R_TimeReport("decals");
7505                 }
7506
7507                 R_DrawParticles();
7508                 if (r_timereport_active)
7509                         R_TimeReport("particles");
7510
7511                 R_DrawExplosions();
7512                 if (r_timereport_active)
7513                         R_TimeReport("explosions");
7514
7515                 R_DrawLightningBeams();
7516                 if (r_timereport_active)
7517                         R_TimeReport("lightning");
7518         }
7519
7520         if (cl.csqc_loaded)
7521                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7522
7523         if (r_refdef.view.showdebug)
7524         {
7525                 if (cl_locs_show.integer)
7526                 {
7527                         R_DrawLocs();
7528                         if (r_timereport_active)
7529                                 R_TimeReport("showlocs");
7530                 }
7531
7532                 if (r_drawportals.integer)
7533                 {
7534                         R_DrawPortals();
7535                         if (r_timereport_active)
7536                                 R_TimeReport("portals");
7537                 }
7538
7539                 if (r_showbboxes.value > 0)
7540                 {
7541                         R_DrawEntityBBoxes();
7542                         if (r_timereport_active)
7543                                 R_TimeReport("bboxes");
7544                 }
7545         }
7546
7547         if (r_transparent.integer)
7548         {
7549                 R_MeshQueue_RenderTransparent();
7550                 if (r_timereport_active)
7551                         R_TimeReport("drawtrans");
7552         }
7553
7554         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))
7555         {
7556                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7557                 if (r_timereport_active)
7558                         R_TimeReport("worlddebug");
7559                 R_DrawModelsDebug();
7560                 if (r_timereport_active)
7561                         R_TimeReport("modeldebug");
7562         }
7563
7564         if (cl.csqc_vidvars.drawworld)
7565         {
7566                 R_Shadow_DrawCoronas();
7567                 if (r_timereport_active)
7568                         R_TimeReport("coronas");
7569         }
7570
7571 #if 0
7572         {
7573                 GL_DepthTest(false);
7574                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7575                 GL_Color(1, 1, 1, 1);
7576                 qglBegin(GL_POLYGON);
7577                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7578                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7579                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7580                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7581                 qglEnd();
7582                 qglBegin(GL_POLYGON);
7583                 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]);
7584                 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]);
7585                 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]);
7586                 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]);
7587                 qglEnd();
7588                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7589         }
7590 #endif
7591
7592         // don't let sound skip if going slow
7593         if (r_refdef.scene.extraupdate)
7594                 S_ExtraUpdate ();
7595 }
7596
7597 static const unsigned short bboxelements[36] =
7598 {
7599         5, 1, 3, 5, 3, 7,
7600         6, 2, 0, 6, 0, 4,
7601         7, 3, 2, 7, 2, 6,
7602         4, 0, 1, 4, 1, 5,
7603         4, 5, 7, 4, 7, 6,
7604         1, 0, 2, 1, 2, 3,
7605 };
7606
7607 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7608 {
7609         int i;
7610         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7611
7612         RSurf_ActiveWorldEntity();
7613
7614         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7615         GL_DepthMask(false);
7616         GL_DepthRange(0, 1);
7617         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7618 //      R_Mesh_ResetTextureState();
7619
7620         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7621         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7622         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7623         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7624         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7625         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7626         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7627         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7628         R_FillColors(color4f, 8, cr, cg, cb, ca);
7629         if (r_refdef.fogenabled)
7630         {
7631                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7632                 {
7633                         f1 = RSurf_FogVertex(v);
7634                         f2 = 1 - f1;
7635                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7636                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7637                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7638                 }
7639         }
7640         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7641         R_Mesh_ResetTextureState();
7642         R_SetupShader_Generic_NoTexture(false, false);
7643         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7644 }
7645
7646 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7647 {
7648         prvm_prog_t *prog = SVVM_prog;
7649         int i;
7650         float color[4];
7651         prvm_edict_t *edict;
7652
7653         // this function draws bounding boxes of server entities
7654         if (!sv.active)
7655                 return;
7656
7657         GL_CullFace(GL_NONE);
7658         R_SetupShader_Generic_NoTexture(false, false);
7659
7660         for (i = 0;i < numsurfaces;i++)
7661         {
7662                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7663                 switch ((int)PRVM_serveredictfloat(edict, solid))
7664                 {
7665                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7666                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7667                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7668                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7669                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7670                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7671                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7672                 }
7673                 color[3] *= r_showbboxes.value;
7674                 color[3] = bound(0, color[3], 1);
7675                 GL_DepthTest(!r_showdisabledepthtest.integer);
7676                 GL_CullFace(r_refdef.view.cullface_front);
7677                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7678         }
7679 }
7680
7681 static void R_DrawEntityBBoxes(void)
7682 {
7683         int i;
7684         prvm_edict_t *edict;
7685         vec3_t center;
7686         prvm_prog_t *prog = SVVM_prog;
7687
7688         // this function draws bounding boxes of server entities
7689         if (!sv.active)
7690                 return;
7691
7692         for (i = 0;i < prog->num_edicts;i++)
7693         {
7694                 edict = PRVM_EDICT_NUM(i);
7695                 if (edict->priv.server->free)
7696                         continue;
7697                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7698                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7699                         continue;
7700                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7701                         continue;
7702                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7703                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7704         }
7705 }
7706
7707 static const int nomodelelement3i[24] =
7708 {
7709         5, 2, 0,
7710         5, 1, 2,
7711         5, 0, 3,
7712         5, 3, 1,
7713         0, 2, 4,
7714         2, 1, 4,
7715         3, 0, 4,
7716         1, 3, 4
7717 };
7718
7719 static const unsigned short nomodelelement3s[24] =
7720 {
7721         5, 2, 0,
7722         5, 1, 2,
7723         5, 0, 3,
7724         5, 3, 1,
7725         0, 2, 4,
7726         2, 1, 4,
7727         3, 0, 4,
7728         1, 3, 4
7729 };
7730
7731 static const float nomodelvertex3f[6*3] =
7732 {
7733         -16,   0,   0,
7734          16,   0,   0,
7735           0, -16,   0,
7736           0,  16,   0,
7737           0,   0, -16,
7738           0,   0,  16
7739 };
7740
7741 static const float nomodelcolor4f[6*4] =
7742 {
7743         0.0f, 0.0f, 0.5f, 1.0f,
7744         0.0f, 0.0f, 0.5f, 1.0f,
7745         0.0f, 0.5f, 0.0f, 1.0f,
7746         0.0f, 0.5f, 0.0f, 1.0f,
7747         0.5f, 0.0f, 0.0f, 1.0f,
7748         0.5f, 0.0f, 0.0f, 1.0f
7749 };
7750
7751 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7752 {
7753         int i;
7754         float f1, f2, *c;
7755         float color4f[6*4];
7756
7757         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);
7758
7759         // this is only called once per entity so numsurfaces is always 1, and
7760         // surfacelist is always {0}, so this code does not handle batches
7761
7762         if (rsurface.ent_flags & RENDER_ADDITIVE)
7763         {
7764                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7765                 GL_DepthMask(false);
7766         }
7767         else if (rsurface.colormod[3] < 1)
7768         {
7769                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7770                 GL_DepthMask(false);
7771         }
7772         else
7773         {
7774                 GL_BlendFunc(GL_ONE, GL_ZERO);
7775                 GL_DepthMask(true);
7776         }
7777         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7778         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7779         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7780         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7781         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7782         for (i = 0, c = color4f;i < 6;i++, c += 4)
7783         {
7784                 c[0] *= rsurface.colormod[0];
7785                 c[1] *= rsurface.colormod[1];
7786                 c[2] *= rsurface.colormod[2];
7787                 c[3] *= rsurface.colormod[3];
7788         }
7789         if (r_refdef.fogenabled)
7790         {
7791                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7792                 {
7793                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7794                         f2 = 1 - f1;
7795                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7796                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7797                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7798                 }
7799         }
7800 //      R_Mesh_ResetTextureState();
7801         R_SetupShader_Generic_NoTexture(false, false);
7802         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7803         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7804 }
7805
7806 void R_DrawNoModel(entity_render_t *ent)
7807 {
7808         vec3_t org;
7809         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7810         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7811                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7812         else
7813                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7814 }
7815
7816 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7817 {
7818         vec3_t right1, right2, diff, normal;
7819
7820         VectorSubtract (org2, org1, normal);
7821
7822         // calculate 'right' vector for start
7823         VectorSubtract (r_refdef.view.origin, org1, diff);
7824         CrossProduct (normal, diff, right1);
7825         VectorNormalize (right1);
7826
7827         // calculate 'right' vector for end
7828         VectorSubtract (r_refdef.view.origin, org2, diff);
7829         CrossProduct (normal, diff, right2);
7830         VectorNormalize (right2);
7831
7832         vert[ 0] = org1[0] + width * right1[0];
7833         vert[ 1] = org1[1] + width * right1[1];
7834         vert[ 2] = org1[2] + width * right1[2];
7835         vert[ 3] = org1[0] - width * right1[0];
7836         vert[ 4] = org1[1] - width * right1[1];
7837         vert[ 5] = org1[2] - width * right1[2];
7838         vert[ 6] = org2[0] - width * right2[0];
7839         vert[ 7] = org2[1] - width * right2[1];
7840         vert[ 8] = org2[2] - width * right2[2];
7841         vert[ 9] = org2[0] + width * right2[0];
7842         vert[10] = org2[1] + width * right2[1];
7843         vert[11] = org2[2] + width * right2[2];
7844 }
7845
7846 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)
7847 {
7848         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7849         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7850         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7851         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7852         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7853         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7854         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7855         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7856         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7857         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7858         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7859         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7860 }
7861
7862 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7863 {
7864         int i;
7865         float *vertex3f;
7866         float v[3];
7867         VectorSet(v, x, y, z);
7868         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7869                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7870                         break;
7871         if (i == mesh->numvertices)
7872         {
7873                 if (mesh->numvertices < mesh->maxvertices)
7874                 {
7875                         VectorCopy(v, vertex3f);
7876                         mesh->numvertices++;
7877                 }
7878                 return mesh->numvertices;
7879         }
7880         else
7881                 return i;
7882 }
7883
7884 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7885 {
7886         int i;
7887         int *e, element[3];
7888         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7889         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7890         e = mesh->element3i + mesh->numtriangles * 3;
7891         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7892         {
7893                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7894                 if (mesh->numtriangles < mesh->maxtriangles)
7895                 {
7896                         *e++ = element[0];
7897                         *e++ = element[1];
7898                         *e++ = element[2];
7899                         mesh->numtriangles++;
7900                 }
7901                 element[1] = element[2];
7902         }
7903 }
7904
7905 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7906 {
7907         int i;
7908         int *e, element[3];
7909         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7910         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7911         e = mesh->element3i + mesh->numtriangles * 3;
7912         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7913         {
7914                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7915                 if (mesh->numtriangles < mesh->maxtriangles)
7916                 {
7917                         *e++ = element[0];
7918                         *e++ = element[1];
7919                         *e++ = element[2];
7920                         mesh->numtriangles++;
7921                 }
7922                 element[1] = element[2];
7923         }
7924 }
7925
7926 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7927 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7928 {
7929         int planenum, planenum2;
7930         int w;
7931         int tempnumpoints;
7932         mplane_t *plane, *plane2;
7933         double maxdist;
7934         double temppoints[2][256*3];
7935         // figure out how large a bounding box we need to properly compute this brush
7936         maxdist = 0;
7937         for (w = 0;w < numplanes;w++)
7938                 maxdist = max(maxdist, fabs(planes[w].dist));
7939         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7940         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7941         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7942         {
7943                 w = 0;
7944                 tempnumpoints = 4;
7945                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7946                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7947                 {
7948                         if (planenum2 == planenum)
7949                                 continue;
7950                         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);
7951                         w = !w;
7952                 }
7953                 if (tempnumpoints < 3)
7954                         continue;
7955                 // generate elements forming a triangle fan for this polygon
7956                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7957         }
7958 }
7959
7960 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)
7961 {
7962         texturelayer_t *layer;
7963         layer = t->currentlayers + t->currentnumlayers++;
7964         layer->type = type;
7965         layer->depthmask = depthmask;
7966         layer->blendfunc1 = blendfunc1;
7967         layer->blendfunc2 = blendfunc2;
7968         layer->texture = texture;
7969         layer->texmatrix = *matrix;
7970         layer->color[0] = r;
7971         layer->color[1] = g;
7972         layer->color[2] = b;
7973         layer->color[3] = a;
7974 }
7975
7976 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7977 {
7978         if(parms[0] == 0 && parms[1] == 0)
7979                 return false;
7980         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7981                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7982                         return false;
7983         return true;
7984 }
7985
7986 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7987 {
7988         double index, f;
7989         index = parms[2] + rsurface.shadertime * parms[3];
7990         index -= floor(index);
7991         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7992         {
7993         default:
7994         case Q3WAVEFUNC_NONE:
7995         case Q3WAVEFUNC_NOISE:
7996         case Q3WAVEFUNC_COUNT:
7997                 f = 0;
7998                 break;
7999         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8000         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8001         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8002         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8003         case Q3WAVEFUNC_TRIANGLE:
8004                 index *= 4;
8005                 f = index - floor(index);
8006                 if (index < 1)
8007                 {
8008                         // f = f;
8009                 }
8010                 else if (index < 2)
8011                         f = 1 - f;
8012                 else if (index < 3)
8013                         f = -f;
8014                 else
8015                         f = -(1 - f);
8016                 break;
8017         }
8018         f = parms[0] + parms[1] * f;
8019         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8020                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8021         return (float) f;
8022 }
8023
8024 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8025 {
8026         int w, h, idx;
8027         float shadertime;
8028         float f;
8029         float offsetd[2];
8030         float tcmat[12];
8031         matrix4x4_t matrix, temp;
8032         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8033         // it's better to have one huge fixup every 9 hours than gradual
8034         // degradation over time which looks consistently bad after many hours.
8035         //
8036         // tcmod scroll in particular suffers from this degradation which can't be
8037         // effectively worked around even with floor() tricks because we don't
8038         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8039         // a workaround involving floor() would be incorrect anyway...
8040         shadertime = rsurface.shadertime;
8041         if (shadertime >= 32768.0f)
8042                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8043         switch(tcmod->tcmod)
8044         {
8045                 case Q3TCMOD_COUNT:
8046                 case Q3TCMOD_NONE:
8047                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8048                                 matrix = r_waterscrollmatrix;
8049                         else
8050                                 matrix = identitymatrix;
8051                         break;
8052                 case Q3TCMOD_ENTITYTRANSLATE:
8053                         // this is used in Q3 to allow the gamecode to control texcoord
8054                         // scrolling on the entity, which is not supported in darkplaces yet.
8055                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8056                         break;
8057                 case Q3TCMOD_ROTATE:
8058                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8059                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8060                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8061                         break;
8062                 case Q3TCMOD_SCALE:
8063                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8064                         break;
8065                 case Q3TCMOD_SCROLL:
8066                         // this particular tcmod is a "bug for bug" compatible one with regards to
8067                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8068                         // specifically did the wrapping and so we must mimic that...
8069                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8070                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8071                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8072                         break;
8073                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8074                         w = (int) tcmod->parms[0];
8075                         h = (int) tcmod->parms[1];
8076                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8077                         f = f - floor(f);
8078                         idx = (int) floor(f * w * h);
8079                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8080                         break;
8081                 case Q3TCMOD_STRETCH:
8082                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8083                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8084                         break;
8085                 case Q3TCMOD_TRANSFORM:
8086                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8087                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8088                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8089                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8090                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8091                         break;
8092                 case Q3TCMOD_TURBULENT:
8093                         // this is handled in the RSurf_PrepareVertices function
8094                         matrix = identitymatrix;
8095                         break;
8096         }
8097         temp = *texmatrix;
8098         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8099 }
8100
8101 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8102 {
8103         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8104         char name[MAX_QPATH];
8105         skinframe_t *skinframe;
8106         unsigned char pixels[296*194];
8107         strlcpy(cache->name, skinname, sizeof(cache->name));
8108         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8109         if (developer_loading.integer)
8110                 Con_Printf("loading %s\n", name);
8111         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8112         if (!skinframe || !skinframe->base)
8113         {
8114                 unsigned char *f;
8115                 fs_offset_t filesize;
8116                 skinframe = NULL;
8117                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8118                 if (f)
8119                 {
8120                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8121                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8122                         Mem_Free(f);
8123                 }
8124         }
8125         cache->skinframe = skinframe;
8126 }
8127
8128 texture_t *R_GetCurrentTexture(texture_t *t)
8129 {
8130         int i;
8131         const entity_render_t *ent = rsurface.entity;
8132         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8133         q3shaderinfo_layer_tcmod_t *tcmod;
8134
8135         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8136                 return t->currentframe;
8137         t->update_lastrenderframe = r_textureframe;
8138         t->update_lastrenderentity = (void *)ent;
8139
8140         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8141                 t->camera_entity = ent->entitynumber;
8142         else
8143                 t->camera_entity = 0;
8144
8145         // switch to an alternate material if this is a q1bsp animated material
8146         {
8147                 texture_t *texture = t;
8148                 int s = rsurface.ent_skinnum;
8149                 if ((unsigned int)s >= (unsigned int)model->numskins)
8150                         s = 0;
8151                 if (model->skinscenes)
8152                 {
8153                         if (model->skinscenes[s].framecount > 1)
8154                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8155                         else
8156                                 s = model->skinscenes[s].firstframe;
8157                 }
8158                 if (s > 0)
8159                         t = t + s * model->num_surfaces;
8160                 if (t->animated)
8161                 {
8162                         // use an alternate animation if the entity's frame is not 0,
8163                         // and only if the texture has an alternate animation
8164                         if (t->animated == 2) // q2bsp
8165                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8166                         else if (rsurface.ent_alttextures && t->anim_total[1])
8167                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8168                         else
8169                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8170                 }
8171                 texture->currentframe = t;
8172         }
8173
8174         // update currentskinframe to be a qw skin or animation frame
8175         if (rsurface.ent_qwskin >= 0)
8176         {
8177                 i = rsurface.ent_qwskin;
8178                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8179                 {
8180                         r_qwskincache_size = cl.maxclients;
8181                         if (r_qwskincache)
8182                                 Mem_Free(r_qwskincache);
8183                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8184                 }
8185                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8186                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8187                 t->currentskinframe = r_qwskincache[i].skinframe;
8188                 if (t->currentskinframe == NULL)
8189                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8190         }
8191         else if (t->numskinframes >= 2)
8192                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8193         if (t->backgroundnumskinframes >= 2)
8194                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8195
8196         t->currentmaterialflags = t->basematerialflags;
8197         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8198         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8199                 t->currentalpha *= r_wateralpha.value;
8200         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8201                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8202         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8203                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8204         if (!(rsurface.ent_flags & RENDER_LIGHT))
8205                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8206         else if (FAKELIGHT_ENABLED)
8207         {
8208                 // no modellight if using fakelight for the map
8209         }
8210         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8211         {
8212                 // pick a model lighting mode
8213                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8214                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8215                 else
8216                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8217         }
8218         if (rsurface.ent_flags & RENDER_ADDITIVE)
8219                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8220         else if (t->currentalpha < 1)
8221                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8222         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8223         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8224                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8225         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8226                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8227         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8228                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8229         if (t->backgroundnumskinframes)
8230                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8231         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8232         {
8233                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8234                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8235         }
8236         else
8237                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8238         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8239         {
8240                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8241                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8242         }
8243         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8244                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8245
8246         // there is no tcmod
8247         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8248         {
8249                 t->currenttexmatrix = r_waterscrollmatrix;
8250                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8251         }
8252         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8253         {
8254                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8255                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8256         }
8257
8258         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8259                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8260         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8261                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8262
8263         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8264         if (t->currentskinframe->qpixels)
8265                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8266         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8267         if (!t->basetexture)
8268                 t->basetexture = r_texture_notexture;
8269         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8270         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8271         t->nmaptexture = t->currentskinframe->nmap;
8272         if (!t->nmaptexture)
8273                 t->nmaptexture = r_texture_blanknormalmap;
8274         t->glosstexture = r_texture_black;
8275         t->glowtexture = t->currentskinframe->glow;
8276         t->fogtexture = t->currentskinframe->fog;
8277         t->reflectmasktexture = t->currentskinframe->reflect;
8278         if (t->backgroundnumskinframes)
8279         {
8280                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8281                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8282                 t->backgroundglosstexture = r_texture_black;
8283                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8284                 if (!t->backgroundnmaptexture)
8285                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8286                 // make sure that if glow is going to be used, both textures are not NULL
8287                 if (!t->backgroundglowtexture && t->glowtexture)
8288                         t->backgroundglowtexture = r_texture_black;
8289                 if (!t->glowtexture && t->backgroundglowtexture)
8290                         t->glowtexture = r_texture_black;
8291         }
8292         else
8293         {
8294                 t->backgroundbasetexture = r_texture_white;
8295                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8296                 t->backgroundglosstexture = r_texture_black;
8297                 t->backgroundglowtexture = NULL;
8298         }
8299         t->specularpower = r_shadow_glossexponent.value;
8300         // TODO: store reference values for these in the texture?
8301         t->specularscale = 0;
8302         if (r_shadow_gloss.integer > 0)
8303         {
8304                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8305                 {
8306                         if (r_shadow_glossintensity.value > 0)
8307                         {
8308                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8309                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8310                                 t->specularscale = r_shadow_glossintensity.value;
8311                         }
8312                 }
8313                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8314                 {
8315                         t->glosstexture = r_texture_white;
8316                         t->backgroundglosstexture = r_texture_white;
8317                         t->specularscale = r_shadow_gloss2intensity.value;
8318                         t->specularpower = r_shadow_gloss2exponent.value;
8319                 }
8320         }
8321         t->specularscale *= t->specularscalemod;
8322         t->specularpower *= t->specularpowermod;
8323         t->rtlightambient = 0;
8324
8325         // lightmaps mode looks bad with dlights using actual texturing, so turn
8326         // off the colormap and glossmap, but leave the normalmap on as it still
8327         // accurately represents the shading involved
8328         if (gl_lightmaps.integer)
8329         {
8330                 t->basetexture = r_texture_grey128;
8331                 t->pantstexture = r_texture_black;
8332                 t->shirttexture = r_texture_black;
8333                 if (gl_lightmaps.integer < 2)
8334                         t->nmaptexture = r_texture_blanknormalmap;
8335                 t->glosstexture = r_texture_black;
8336                 t->glowtexture = NULL;
8337                 t->fogtexture = NULL;
8338                 t->reflectmasktexture = NULL;
8339                 t->backgroundbasetexture = NULL;
8340                 if (gl_lightmaps.integer < 2)
8341                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8342                 t->backgroundglosstexture = r_texture_black;
8343                 t->backgroundglowtexture = NULL;
8344                 t->specularscale = 0;
8345                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8346         }
8347
8348         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8349         VectorClear(t->dlightcolor);
8350         t->currentnumlayers = 0;
8351         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8352         {
8353                 int blendfunc1, blendfunc2;
8354                 qboolean depthmask;
8355                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8356                 {
8357                         blendfunc1 = GL_SRC_ALPHA;
8358                         blendfunc2 = GL_ONE;
8359                 }
8360                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8361                 {
8362                         blendfunc1 = GL_SRC_ALPHA;
8363                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8364                 }
8365                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8366                 {
8367                         blendfunc1 = t->customblendfunc[0];
8368                         blendfunc2 = t->customblendfunc[1];
8369                 }
8370                 else
8371                 {
8372                         blendfunc1 = GL_ONE;
8373                         blendfunc2 = GL_ZERO;
8374                 }
8375                 // don't colormod evilblend textures
8376                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8377                         VectorSet(t->lightmapcolor, 1, 1, 1);
8378                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8379                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8380                 {
8381                         // fullbright is not affected by r_refdef.lightmapintensity
8382                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8383                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8384                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8385                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8386                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8387                 }
8388                 else
8389                 {
8390                         vec3_t ambientcolor;
8391                         float colorscale;
8392                         // set the color tint used for lights affecting this surface
8393                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8394                         colorscale = 2;
8395                         // q3bsp has no lightmap updates, so the lightstylevalue that
8396                         // would normally be baked into the lightmap must be
8397                         // applied to the color
8398                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8399                         if (model->type == mod_brushq3)
8400                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8401                         colorscale *= r_refdef.lightmapintensity;
8402                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8403                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8404                         // basic lit geometry
8405                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8406                         // add pants/shirt if needed
8407                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8408                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
8409                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8410                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8411                         // now add ambient passes if needed
8412                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8413                         {
8414                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
8415                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8416                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8417                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8418                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8419                         }
8420                 }
8421                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8422                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
8423                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8424                 {
8425                         // if this is opaque use alpha blend which will darken the earlier
8426                         // passes cheaply.
8427                         //
8428                         // if this is an alpha blended material, all the earlier passes
8429                         // were darkened by fog already, so we only need to add the fog
8430                         // color ontop through the fog mask texture
8431                         //
8432                         // if this is an additive blended material, all the earlier passes
8433                         // were darkened by fog already, and we should not add fog color
8434                         // (because the background was not darkened, there is no fog color
8435                         // that was lost behind it).
8436                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
8437                 }
8438         }
8439
8440         return t;
8441 }
8442
8443 rsurfacestate_t rsurface;
8444
8445 void RSurf_ActiveWorldEntity(void)
8446 {
8447         dp_model_t *model = r_refdef.scene.worldmodel;
8448         //if (rsurface.entity == r_refdef.scene.worldentity)
8449         //      return;
8450         rsurface.entity = r_refdef.scene.worldentity;
8451         rsurface.skeleton = NULL;
8452         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8453         rsurface.ent_skinnum = 0;
8454         rsurface.ent_qwskin = -1;
8455         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8456         rsurface.shadertime = r_refdef.scene.time;
8457         rsurface.matrix = identitymatrix;
8458         rsurface.inversematrix = identitymatrix;
8459         rsurface.matrixscale = 1;
8460         rsurface.inversematrixscale = 1;
8461         R_EntityMatrix(&identitymatrix);
8462         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8463         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8464         rsurface.fograngerecip = r_refdef.fograngerecip;
8465         rsurface.fogheightfade = r_refdef.fogheightfade;
8466         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8467         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8468         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8469         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8470         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8471         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8472         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8473         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8474         rsurface.colormod[3] = 1;
8475         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8476         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8477         rsurface.frameblend[0].lerp = 1;
8478         rsurface.ent_alttextures = false;
8479         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8480         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8481         rsurface.entityskeletaltransform3x4 = NULL;
8482         rsurface.entityskeletaltransform3x4buffer = NULL;
8483         rsurface.entityskeletaltransform3x4offset = 0;
8484         rsurface.entityskeletaltransform3x4size = 0;;
8485         rsurface.entityskeletalnumtransforms = 0;
8486         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8487         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8488         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8489         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8490         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8491         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8492         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8493         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8494         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8495         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8496         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8497         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8498         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8499         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8500         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8501         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8502         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8503         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8504         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8505         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8506         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8507         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8508         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8509         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8510         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8511         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8512         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8513         rsurface.modelelement3i = model->surfmesh.data_element3i;
8514         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8515         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8516         rsurface.modelelement3s = model->surfmesh.data_element3s;
8517         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8518         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8519         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8520         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8521         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8522         rsurface.modelsurfaces = model->data_surfaces;
8523         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8524         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8525         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8526         rsurface.modelgeneratedvertex = false;
8527         rsurface.batchgeneratedvertex = false;
8528         rsurface.batchfirstvertex = 0;
8529         rsurface.batchnumvertices = 0;
8530         rsurface.batchfirsttriangle = 0;
8531         rsurface.batchnumtriangles = 0;
8532         rsurface.batchvertex3f  = NULL;
8533         rsurface.batchvertex3f_vertexbuffer = NULL;
8534         rsurface.batchvertex3f_bufferoffset = 0;
8535         rsurface.batchsvector3f = NULL;
8536         rsurface.batchsvector3f_vertexbuffer = NULL;
8537         rsurface.batchsvector3f_bufferoffset = 0;
8538         rsurface.batchtvector3f = NULL;
8539         rsurface.batchtvector3f_vertexbuffer = NULL;
8540         rsurface.batchtvector3f_bufferoffset = 0;
8541         rsurface.batchnormal3f  = NULL;
8542         rsurface.batchnormal3f_vertexbuffer = NULL;
8543         rsurface.batchnormal3f_bufferoffset = 0;
8544         rsurface.batchlightmapcolor4f = NULL;
8545         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8546         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8547         rsurface.batchtexcoordtexture2f = NULL;
8548         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8549         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8550         rsurface.batchtexcoordlightmap2f = NULL;
8551         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8552         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8553         rsurface.batchskeletalindex4ub = NULL;
8554         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8555         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8556         rsurface.batchskeletalweight4ub = NULL;
8557         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8558         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8559         rsurface.batchvertexmesh = NULL;
8560         rsurface.batchvertexmesh_vertexbuffer = NULL;
8561         rsurface.batchvertexmesh_bufferoffset = 0;
8562         rsurface.batchelement3i = NULL;
8563         rsurface.batchelement3i_indexbuffer = NULL;
8564         rsurface.batchelement3i_bufferoffset = 0;
8565         rsurface.batchelement3s = NULL;
8566         rsurface.batchelement3s_indexbuffer = NULL;
8567         rsurface.batchelement3s_bufferoffset = 0;
8568         rsurface.passcolor4f = NULL;
8569         rsurface.passcolor4f_vertexbuffer = NULL;
8570         rsurface.passcolor4f_bufferoffset = 0;
8571         rsurface.forcecurrenttextureupdate = false;
8572 }
8573
8574 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8575 {
8576         dp_model_t *model = ent->model;
8577         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8578         //      return;
8579         rsurface.entity = (entity_render_t *)ent;
8580         rsurface.skeleton = ent->skeleton;
8581         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8582         rsurface.ent_skinnum = ent->skinnum;
8583         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;
8584         rsurface.ent_flags = ent->flags;
8585         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8586         rsurface.matrix = ent->matrix;
8587         rsurface.inversematrix = ent->inversematrix;
8588         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8589         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8590         R_EntityMatrix(&rsurface.matrix);
8591         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8592         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8593         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8594         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8595         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8596         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8597         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8598         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8599         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8600         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8601         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8602         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8603         rsurface.colormod[3] = ent->alpha;
8604         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8605         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8606         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8607         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8608         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8609         if (ent->model->brush.submodel && !prepass)
8610         {
8611                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8612                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8613         }
8614         // if the animcache code decided it should use the shader path, skip the deform step
8615         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8616         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8617         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8618         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8619         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8620         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8621         {
8622                 if (ent->animcache_vertex3f)
8623                 {
8624                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8625                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8626                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8627                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8628                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8629                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8630                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8631                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8632                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8633                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8634                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8635                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8636                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8637                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8638                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8639                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8640                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8641                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8642                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8643                 }
8644                 else if (wanttangents)
8645                 {
8646                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8647                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8648                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8649                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8650                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8651                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8652                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8653                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8654                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8655                         rsurface.modelvertexmesh = NULL;
8656                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8657                         rsurface.modelvertexmesh_bufferoffset = 0;
8658                         rsurface.modelvertex3f_vertexbuffer = NULL;
8659                         rsurface.modelvertex3f_bufferoffset = 0;
8660                         rsurface.modelvertex3f_vertexbuffer = 0;
8661                         rsurface.modelvertex3f_bufferoffset = 0;
8662                         rsurface.modelsvector3f_vertexbuffer = 0;
8663                         rsurface.modelsvector3f_bufferoffset = 0;
8664                         rsurface.modeltvector3f_vertexbuffer = 0;
8665                         rsurface.modeltvector3f_bufferoffset = 0;
8666                         rsurface.modelnormal3f_vertexbuffer = 0;
8667                         rsurface.modelnormal3f_bufferoffset = 0;
8668                 }
8669                 else if (wantnormals)
8670                 {
8671                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8672                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8673                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8674                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8675                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8676                         rsurface.modelsvector3f = NULL;
8677                         rsurface.modeltvector3f = NULL;
8678                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8679                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8680                         rsurface.modelvertexmesh = NULL;
8681                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8682                         rsurface.modelvertexmesh_bufferoffset = 0;
8683                         rsurface.modelvertex3f_vertexbuffer = NULL;
8684                         rsurface.modelvertex3f_bufferoffset = 0;
8685                         rsurface.modelvertex3f_vertexbuffer = 0;
8686                         rsurface.modelvertex3f_bufferoffset = 0;
8687                         rsurface.modelsvector3f_vertexbuffer = 0;
8688                         rsurface.modelsvector3f_bufferoffset = 0;
8689                         rsurface.modeltvector3f_vertexbuffer = 0;
8690                         rsurface.modeltvector3f_bufferoffset = 0;
8691                         rsurface.modelnormal3f_vertexbuffer = 0;
8692                         rsurface.modelnormal3f_bufferoffset = 0;
8693                 }
8694                 else
8695                 {
8696                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8697                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8698                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8699                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8700                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8701                         rsurface.modelsvector3f = NULL;
8702                         rsurface.modeltvector3f = NULL;
8703                         rsurface.modelnormal3f = NULL;
8704                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8705                         rsurface.modelvertexmesh = NULL;
8706                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8707                         rsurface.modelvertexmesh_bufferoffset = 0;
8708                         rsurface.modelvertex3f_vertexbuffer = NULL;
8709                         rsurface.modelvertex3f_bufferoffset = 0;
8710                         rsurface.modelvertex3f_vertexbuffer = 0;
8711                         rsurface.modelvertex3f_bufferoffset = 0;
8712                         rsurface.modelsvector3f_vertexbuffer = 0;
8713                         rsurface.modelsvector3f_bufferoffset = 0;
8714                         rsurface.modeltvector3f_vertexbuffer = 0;
8715                         rsurface.modeltvector3f_bufferoffset = 0;
8716                         rsurface.modelnormal3f_vertexbuffer = 0;
8717                         rsurface.modelnormal3f_bufferoffset = 0;
8718                 }
8719                 rsurface.modelgeneratedvertex = true;
8720         }
8721         else
8722         {
8723                 if (rsurface.entityskeletaltransform3x4)
8724                 {
8725                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8726                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8727                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8728                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8729                 }
8730                 else
8731                 {
8732                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8733                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8734                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8735                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8736                 }
8737                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8738                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8739                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8740                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8741                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8742                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8743                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8744                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8745                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8746                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8747                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8748                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8749                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8750                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8751                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8752                 rsurface.modelgeneratedvertex = false;
8753         }
8754         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8755         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8756         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8757         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8758         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8759         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8760         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8761         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8762         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8763         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8764         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8765         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8766         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8767         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8768         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8769         rsurface.modelelement3i = model->surfmesh.data_element3i;
8770         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8771         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8772         rsurface.modelelement3s = model->surfmesh.data_element3s;
8773         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8774         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8775         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8776         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8777         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8778         rsurface.modelsurfaces = model->data_surfaces;
8779         rsurface.batchgeneratedvertex = false;
8780         rsurface.batchfirstvertex = 0;
8781         rsurface.batchnumvertices = 0;
8782         rsurface.batchfirsttriangle = 0;
8783         rsurface.batchnumtriangles = 0;
8784         rsurface.batchvertex3f  = NULL;
8785         rsurface.batchvertex3f_vertexbuffer = NULL;
8786         rsurface.batchvertex3f_bufferoffset = 0;
8787         rsurface.batchsvector3f = NULL;
8788         rsurface.batchsvector3f_vertexbuffer = NULL;
8789         rsurface.batchsvector3f_bufferoffset = 0;
8790         rsurface.batchtvector3f = NULL;
8791         rsurface.batchtvector3f_vertexbuffer = NULL;
8792         rsurface.batchtvector3f_bufferoffset = 0;
8793         rsurface.batchnormal3f  = NULL;
8794         rsurface.batchnormal3f_vertexbuffer = NULL;
8795         rsurface.batchnormal3f_bufferoffset = 0;
8796         rsurface.batchlightmapcolor4f = NULL;
8797         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8798         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8799         rsurface.batchtexcoordtexture2f = NULL;
8800         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8801         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8802         rsurface.batchtexcoordlightmap2f = NULL;
8803         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8804         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8805         rsurface.batchskeletalindex4ub = NULL;
8806         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8807         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8808         rsurface.batchskeletalweight4ub = NULL;
8809         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8810         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8811         rsurface.batchvertexmesh = NULL;
8812         rsurface.batchvertexmesh_vertexbuffer = NULL;
8813         rsurface.batchvertexmesh_bufferoffset = 0;
8814         rsurface.batchelement3i = NULL;
8815         rsurface.batchelement3i_indexbuffer = NULL;
8816         rsurface.batchelement3i_bufferoffset = 0;
8817         rsurface.batchelement3s = NULL;
8818         rsurface.batchelement3s_indexbuffer = NULL;
8819         rsurface.batchelement3s_bufferoffset = 0;
8820         rsurface.passcolor4f = NULL;
8821         rsurface.passcolor4f_vertexbuffer = NULL;
8822         rsurface.passcolor4f_bufferoffset = 0;
8823         rsurface.forcecurrenttextureupdate = false;
8824 }
8825
8826 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)
8827 {
8828         rsurface.entity = r_refdef.scene.worldentity;
8829         rsurface.skeleton = NULL;
8830         rsurface.ent_skinnum = 0;
8831         rsurface.ent_qwskin = -1;
8832         rsurface.ent_flags = entflags;
8833         rsurface.shadertime = r_refdef.scene.time - shadertime;
8834         rsurface.modelnumvertices = numvertices;
8835         rsurface.modelnumtriangles = numtriangles;
8836         rsurface.matrix = *matrix;
8837         rsurface.inversematrix = *inversematrix;
8838         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8839         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8840         R_EntityMatrix(&rsurface.matrix);
8841         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8842         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8843         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8844         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8845         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8846         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8847         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8848         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8849         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8850         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8851         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8852         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8853         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8854         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8855         rsurface.frameblend[0].lerp = 1;
8856         rsurface.ent_alttextures = false;
8857         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8858         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8859         rsurface.entityskeletaltransform3x4 = NULL;
8860         rsurface.entityskeletaltransform3x4buffer = NULL;
8861         rsurface.entityskeletaltransform3x4offset = 0;
8862         rsurface.entityskeletaltransform3x4size = 0;
8863         rsurface.entityskeletalnumtransforms = 0;
8864         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8865         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8866         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8867         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8868         if (wanttangents)
8869         {
8870                 rsurface.modelvertex3f = (float *)vertex3f;
8871                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8872                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8873                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8874         }
8875         else if (wantnormals)
8876         {
8877                 rsurface.modelvertex3f = (float *)vertex3f;
8878                 rsurface.modelsvector3f = NULL;
8879                 rsurface.modeltvector3f = NULL;
8880                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8881         }
8882         else
8883         {
8884                 rsurface.modelvertex3f = (float *)vertex3f;
8885                 rsurface.modelsvector3f = NULL;
8886                 rsurface.modeltvector3f = NULL;
8887                 rsurface.modelnormal3f = NULL;
8888         }
8889         rsurface.modelvertexmesh = NULL;
8890         rsurface.modelvertexmesh_vertexbuffer = NULL;
8891         rsurface.modelvertexmesh_bufferoffset = 0;
8892         rsurface.modelvertex3f_vertexbuffer = 0;
8893         rsurface.modelvertex3f_bufferoffset = 0;
8894         rsurface.modelsvector3f_vertexbuffer = 0;
8895         rsurface.modelsvector3f_bufferoffset = 0;
8896         rsurface.modeltvector3f_vertexbuffer = 0;
8897         rsurface.modeltvector3f_bufferoffset = 0;
8898         rsurface.modelnormal3f_vertexbuffer = 0;
8899         rsurface.modelnormal3f_bufferoffset = 0;
8900         rsurface.modelgeneratedvertex = true;
8901         rsurface.modellightmapcolor4f  = (float *)color4f;
8902         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8903         rsurface.modellightmapcolor4f_bufferoffset = 0;
8904         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8905         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8906         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8907         rsurface.modeltexcoordlightmap2f  = NULL;
8908         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8909         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8910         rsurface.modelskeletalindex4ub = NULL;
8911         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8912         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8913         rsurface.modelskeletalweight4ub = NULL;
8914         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8915         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8916         rsurface.modelelement3i = (int *)element3i;
8917         rsurface.modelelement3i_indexbuffer = NULL;
8918         rsurface.modelelement3i_bufferoffset = 0;
8919         rsurface.modelelement3s = (unsigned short *)element3s;
8920         rsurface.modelelement3s_indexbuffer = NULL;
8921         rsurface.modelelement3s_bufferoffset = 0;
8922         rsurface.modellightmapoffsets = NULL;
8923         rsurface.modelsurfaces = NULL;
8924         rsurface.batchgeneratedvertex = false;
8925         rsurface.batchfirstvertex = 0;
8926         rsurface.batchnumvertices = 0;
8927         rsurface.batchfirsttriangle = 0;
8928         rsurface.batchnumtriangles = 0;
8929         rsurface.batchvertex3f  = NULL;
8930         rsurface.batchvertex3f_vertexbuffer = NULL;
8931         rsurface.batchvertex3f_bufferoffset = 0;
8932         rsurface.batchsvector3f = NULL;
8933         rsurface.batchsvector3f_vertexbuffer = NULL;
8934         rsurface.batchsvector3f_bufferoffset = 0;
8935         rsurface.batchtvector3f = NULL;
8936         rsurface.batchtvector3f_vertexbuffer = NULL;
8937         rsurface.batchtvector3f_bufferoffset = 0;
8938         rsurface.batchnormal3f  = NULL;
8939         rsurface.batchnormal3f_vertexbuffer = NULL;
8940         rsurface.batchnormal3f_bufferoffset = 0;
8941         rsurface.batchlightmapcolor4f = NULL;
8942         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8943         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8944         rsurface.batchtexcoordtexture2f = NULL;
8945         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8946         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8947         rsurface.batchtexcoordlightmap2f = NULL;
8948         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8949         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8950         rsurface.batchskeletalindex4ub = NULL;
8951         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8952         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8953         rsurface.batchskeletalweight4ub = NULL;
8954         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8955         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8956         rsurface.batchvertexmesh = NULL;
8957         rsurface.batchvertexmesh_vertexbuffer = NULL;
8958         rsurface.batchvertexmesh_bufferoffset = 0;
8959         rsurface.batchelement3i = NULL;
8960         rsurface.batchelement3i_indexbuffer = NULL;
8961         rsurface.batchelement3i_bufferoffset = 0;
8962         rsurface.batchelement3s = NULL;
8963         rsurface.batchelement3s_indexbuffer = NULL;
8964         rsurface.batchelement3s_bufferoffset = 0;
8965         rsurface.passcolor4f = NULL;
8966         rsurface.passcolor4f_vertexbuffer = NULL;
8967         rsurface.passcolor4f_bufferoffset = 0;
8968         rsurface.forcecurrenttextureupdate = true;
8969
8970         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8971         {
8972                 if ((wantnormals || wanttangents) && !normal3f)
8973                 {
8974                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8975                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8976                 }
8977                 if (wanttangents && !svector3f)
8978                 {
8979                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8980                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8981                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8982                 }
8983         }
8984 }
8985
8986 float RSurf_FogPoint(const float *v)
8987 {
8988         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8989         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8990         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8991         float FogHeightFade = r_refdef.fogheightfade;
8992         float fogfrac;
8993         unsigned int fogmasktableindex;
8994         if (r_refdef.fogplaneviewabove)
8995                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8996         else
8997                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8998         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8999         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9000 }
9001
9002 float RSurf_FogVertex(const float *v)
9003 {
9004         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9005         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9006         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9007         float FogHeightFade = rsurface.fogheightfade;
9008         float fogfrac;
9009         unsigned int fogmasktableindex;
9010         if (r_refdef.fogplaneviewabove)
9011                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9012         else
9013                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9014         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9015         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9016 }
9017
9018 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9019 {
9020         int i;
9021         for (i = 0;i < numelements;i++)
9022                 outelement3i[i] = inelement3i[i] + adjust;
9023 }
9024
9025 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9026 extern cvar_t gl_vbo;
9027 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9028 {
9029         int deformindex;
9030         int firsttriangle;
9031         int numtriangles;
9032         int firstvertex;
9033         int endvertex;
9034         int numvertices;
9035         int surfacefirsttriangle;
9036         int surfacenumtriangles;
9037         int surfacefirstvertex;
9038         int surfaceendvertex;
9039         int surfacenumvertices;
9040         int batchnumsurfaces = texturenumsurfaces;
9041         int batchnumvertices;
9042         int batchnumtriangles;
9043         int needsupdate;
9044         int i, j;
9045         qboolean gaps;
9046         qboolean dynamicvertex;
9047         float amplitude;
9048         float animpos;
9049         float scale;
9050         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9051         float waveparms[4];
9052         unsigned char *ub;
9053         q3shaderinfo_deform_t *deform;
9054         const msurface_t *surface, *firstsurface;
9055         r_vertexmesh_t *vertexmesh;
9056         if (!texturenumsurfaces)
9057                 return;
9058         // find vertex range of this surface batch
9059         gaps = false;
9060         firstsurface = texturesurfacelist[0];
9061         firsttriangle = firstsurface->num_firsttriangle;
9062         batchnumvertices = 0;
9063         batchnumtriangles = 0;
9064         firstvertex = endvertex = firstsurface->num_firstvertex;
9065         for (i = 0;i < texturenumsurfaces;i++)
9066         {
9067                 surface = texturesurfacelist[i];
9068                 if (surface != firstsurface + i)
9069                         gaps = true;
9070                 surfacefirstvertex = surface->num_firstvertex;
9071                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9072                 surfacenumvertices = surface->num_vertices;
9073                 surfacenumtriangles = surface->num_triangles;
9074                 if (firstvertex > surfacefirstvertex)
9075                         firstvertex = surfacefirstvertex;
9076                 if (endvertex < surfaceendvertex)
9077                         endvertex = surfaceendvertex;
9078                 batchnumvertices += surfacenumvertices;
9079                 batchnumtriangles += surfacenumtriangles;
9080         }
9081
9082         r_refdef.stats[r_stat_batch_batches]++;
9083         if (gaps)
9084                 r_refdef.stats[r_stat_batch_withgaps]++;
9085         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9086         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9087         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9088
9089         // we now know the vertex range used, and if there are any gaps in it
9090         rsurface.batchfirstvertex = firstvertex;
9091         rsurface.batchnumvertices = endvertex - firstvertex;
9092         rsurface.batchfirsttriangle = firsttriangle;
9093         rsurface.batchnumtriangles = batchnumtriangles;
9094
9095         // this variable holds flags for which properties have been updated that
9096         // may require regenerating vertexmesh array...
9097         needsupdate = 0;
9098
9099         // check if any dynamic vertex processing must occur
9100         dynamicvertex = false;
9101
9102         // a cvar to force the dynamic vertex path to be taken, for debugging
9103         if (r_batch_debugdynamicvertexpath.integer)
9104         {
9105                 if (!dynamicvertex)
9106                 {
9107                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9108                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9109                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9110                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9111                 }
9112                 dynamicvertex = true;
9113         }
9114
9115         // if there is a chance of animated vertex colors, it's a dynamic batch
9116         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9117         {
9118                 if (!dynamicvertex)
9119                 {
9120                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9121                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9122                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9123                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9124                 }
9125                 dynamicvertex = true;
9126                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9127         }
9128
9129         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9130         {
9131                 switch (deform->deform)
9132                 {
9133                 default:
9134                 case Q3DEFORM_PROJECTIONSHADOW:
9135                 case Q3DEFORM_TEXT0:
9136                 case Q3DEFORM_TEXT1:
9137                 case Q3DEFORM_TEXT2:
9138                 case Q3DEFORM_TEXT3:
9139                 case Q3DEFORM_TEXT4:
9140                 case Q3DEFORM_TEXT5:
9141                 case Q3DEFORM_TEXT6:
9142                 case Q3DEFORM_TEXT7:
9143                 case Q3DEFORM_NONE:
9144                         break;
9145                 case Q3DEFORM_AUTOSPRITE:
9146                         if (!dynamicvertex)
9147                         {
9148                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9149                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9150                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9151                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9152                         }
9153                         dynamicvertex = true;
9154                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9155                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9156                         break;
9157                 case Q3DEFORM_AUTOSPRITE2:
9158                         if (!dynamicvertex)
9159                         {
9160                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9161                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9162                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9163                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9164                         }
9165                         dynamicvertex = true;
9166                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9167                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9168                         break;
9169                 case Q3DEFORM_NORMAL:
9170                         if (!dynamicvertex)
9171                         {
9172                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9173                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9174                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9175                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9176                         }
9177                         dynamicvertex = true;
9178                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9179                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9180                         break;
9181                 case Q3DEFORM_WAVE:
9182                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9183                                 break; // if wavefunc is a nop, ignore this transform
9184                         if (!dynamicvertex)
9185                         {
9186                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9187                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9188                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9189                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9190                         }
9191                         dynamicvertex = true;
9192                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9193                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9194                         break;
9195                 case Q3DEFORM_BULGE:
9196                         if (!dynamicvertex)
9197                         {
9198                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9199                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9200                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9201                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9202                         }
9203                         dynamicvertex = true;
9204                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9205                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9206                         break;
9207                 case Q3DEFORM_MOVE:
9208                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9209                                 break; // if wavefunc is a nop, ignore this transform
9210                         if (!dynamicvertex)
9211                         {
9212                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9213                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9214                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9215                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9216                         }
9217                         dynamicvertex = true;
9218                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9219                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9220                         break;
9221                 }
9222         }
9223         switch(rsurface.texture->tcgen.tcgen)
9224         {
9225         default:
9226         case Q3TCGEN_TEXTURE:
9227                 break;
9228         case Q3TCGEN_LIGHTMAP:
9229                 if (!dynamicvertex)
9230                 {
9231                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9232                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9233                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9234                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9235                 }
9236                 dynamicvertex = true;
9237                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9238                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9239                 break;
9240         case Q3TCGEN_VECTOR:
9241                 if (!dynamicvertex)
9242                 {
9243                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9244                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9245                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9246                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9247                 }
9248                 dynamicvertex = true;
9249                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9250                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9251                 break;
9252         case Q3TCGEN_ENVIRONMENT:
9253                 if (!dynamicvertex)
9254                 {
9255                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9256                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9257                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9258                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9259                 }
9260                 dynamicvertex = true;
9261                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9262                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9263                 break;
9264         }
9265         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9266         {
9267                 if (!dynamicvertex)
9268                 {
9269                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9270                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9271                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9272                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9273                 }
9274                 dynamicvertex = true;
9275                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9276                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9277         }
9278
9279         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9280         {
9281                 if (!dynamicvertex)
9282                 {
9283                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9284                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9285                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9286                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9287                 }
9288                 dynamicvertex = true;
9289                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9290         }
9291
9292         // when the model data has no vertex buffer (dynamic mesh), we need to
9293         // eliminate gaps
9294         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9295                 batchneed |= BATCHNEED_NOGAPS;
9296
9297         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9298         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9299         // we ensure this by treating the vertex batch as dynamic...
9300         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9301         {
9302                 if (!dynamicvertex)
9303                 {
9304                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9305                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9306                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9307                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9308                 }
9309                 dynamicvertex = true;
9310         }
9311
9312         if (dynamicvertex)
9313         {
9314                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9315                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9316                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9317                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9318                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9319                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9320                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9321                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9322         }
9323
9324         // if needsupdate, we have to do a dynamic vertex batch for sure
9325         if (needsupdate & batchneed)
9326         {
9327                 if (!dynamicvertex)
9328                 {
9329                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9330                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9331                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9332                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9333                 }
9334                 dynamicvertex = true;
9335         }
9336
9337         // see if we need to build vertexmesh from arrays
9338         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9339         {
9340                 if (!dynamicvertex)
9341                 {
9342                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9343                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9344                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9345                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9346                 }
9347                 dynamicvertex = true;
9348         }
9349
9350         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9351         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9352                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9353
9354         rsurface.batchvertex3f = rsurface.modelvertex3f;
9355         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9356         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9357         rsurface.batchsvector3f = rsurface.modelsvector3f;
9358         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9359         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9360         rsurface.batchtvector3f = rsurface.modeltvector3f;
9361         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9362         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9363         rsurface.batchnormal3f = rsurface.modelnormal3f;
9364         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9365         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9366         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9367         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9368         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9369         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9370         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9371         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9372         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9373         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9374         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9375         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9376         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9377         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9378         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9379         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9380         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9381         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9382         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9383         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9384         rsurface.batchelement3i = rsurface.modelelement3i;
9385         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9386         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9387         rsurface.batchelement3s = rsurface.modelelement3s;
9388         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9389         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9390         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9391         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9392         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9393         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9394         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9395
9396         // if any dynamic vertex processing has to occur in software, we copy the
9397         // entire surface list together before processing to rebase the vertices
9398         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9399         //
9400         // if any gaps exist and we do not have a static vertex buffer, we have to
9401         // copy the surface list together to avoid wasting upload bandwidth on the
9402         // vertices in the gaps.
9403         //
9404         // if gaps exist and we have a static vertex buffer, we can choose whether
9405         // to combine the index buffer ranges into one dynamic index buffer or
9406         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9407         //
9408         // in many cases the batch is reduced to one draw call.
9409
9410         rsurface.batchmultidraw = false;
9411         rsurface.batchmultidrawnumsurfaces = 0;
9412         rsurface.batchmultidrawsurfacelist = NULL;
9413
9414         if (!dynamicvertex)
9415         {
9416                 // static vertex data, just set pointers...
9417                 rsurface.batchgeneratedvertex = false;
9418                 // if there are gaps, we want to build a combined index buffer,
9419                 // otherwise use the original static buffer with an appropriate offset
9420                 if (gaps)
9421                 {
9422                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9423                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9424                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9425                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9426                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9427                         {
9428                                 rsurface.batchmultidraw = true;
9429                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9430                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9431                                 return;
9432                         }
9433                         // build a new triangle elements array for this batch
9434                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9435                         rsurface.batchfirsttriangle = 0;
9436                         numtriangles = 0;
9437                         for (i = 0;i < texturenumsurfaces;i++)
9438                         {
9439                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9440                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9441                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9442                                 numtriangles += surfacenumtriangles;
9443                         }
9444                         rsurface.batchelement3i_indexbuffer = NULL;
9445                         rsurface.batchelement3i_bufferoffset = 0;
9446                         rsurface.batchelement3s = NULL;
9447                         rsurface.batchelement3s_indexbuffer = NULL;
9448                         rsurface.batchelement3s_bufferoffset = 0;
9449                         if (endvertex <= 65536)
9450                         {
9451                                 // make a 16bit (unsigned short) index array if possible
9452                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9453                                 for (i = 0;i < numtriangles*3;i++)
9454                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9455                         }
9456                         // upload buffer data for the copytriangles batch
9457                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9458                         {
9459                                 if (rsurface.batchelement3s)
9460                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9461                                 else if (rsurface.batchelement3i)
9462                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9463                         }
9464                 }
9465                 else
9466                 {
9467                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9468                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9469                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9470                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9471                 }
9472                 return;
9473         }
9474
9475         // something needs software processing, do it for real...
9476         // we only directly handle separate array data in this case and then
9477         // generate interleaved data if needed...
9478         rsurface.batchgeneratedvertex = true;
9479         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9480         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9481         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9482         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9483
9484         // now copy the vertex data into a combined array and make an index array
9485         // (this is what Quake3 does all the time)
9486         // we also apply any skeletal animation here that would have been done in
9487         // the vertex shader, because most of the dynamic vertex animation cases
9488         // need actual vertex positions and normals
9489         //if (dynamicvertex)
9490         {
9491                 rsurface.batchvertexmesh = NULL;
9492                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9493                 rsurface.batchvertexmesh_bufferoffset = 0;
9494                 rsurface.batchvertex3f = NULL;
9495                 rsurface.batchvertex3f_vertexbuffer = NULL;
9496                 rsurface.batchvertex3f_bufferoffset = 0;
9497                 rsurface.batchsvector3f = NULL;
9498                 rsurface.batchsvector3f_vertexbuffer = NULL;
9499                 rsurface.batchsvector3f_bufferoffset = 0;
9500                 rsurface.batchtvector3f = NULL;
9501                 rsurface.batchtvector3f_vertexbuffer = NULL;
9502                 rsurface.batchtvector3f_bufferoffset = 0;
9503                 rsurface.batchnormal3f = NULL;
9504                 rsurface.batchnormal3f_vertexbuffer = NULL;
9505                 rsurface.batchnormal3f_bufferoffset = 0;
9506                 rsurface.batchlightmapcolor4f = NULL;
9507                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9508                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9509                 rsurface.batchtexcoordtexture2f = NULL;
9510                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9511                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9512                 rsurface.batchtexcoordlightmap2f = NULL;
9513                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9514                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9515                 rsurface.batchskeletalindex4ub = NULL;
9516                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9517                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9518                 rsurface.batchskeletalweight4ub = NULL;
9519                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9520                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9521                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9522                 rsurface.batchelement3i_indexbuffer = NULL;
9523                 rsurface.batchelement3i_bufferoffset = 0;
9524                 rsurface.batchelement3s = NULL;
9525                 rsurface.batchelement3s_indexbuffer = NULL;
9526                 rsurface.batchelement3s_bufferoffset = 0;
9527                 rsurface.batchskeletaltransform3x4buffer = NULL;
9528                 rsurface.batchskeletaltransform3x4offset = 0;
9529                 rsurface.batchskeletaltransform3x4size = 0;
9530                 // we'll only be setting up certain arrays as needed
9531                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9532                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9533                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9534                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9535                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9536                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9537                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9538                 {
9539                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9540                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9541                 }
9542                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9543                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9544                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9545                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9546                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9547                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9548                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9549                 {
9550                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9551                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9552                 }
9553                 numvertices = 0;
9554                 numtriangles = 0;
9555                 for (i = 0;i < texturenumsurfaces;i++)
9556                 {
9557                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9558                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9559                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9560                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9561                         // copy only the data requested
9562                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9563                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9564                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9565                         {
9566                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9567                                 {
9568                                         if (rsurface.batchvertex3f)
9569                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9570                                         else
9571                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9572                                 }
9573                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9574                                 {
9575                                         if (rsurface.modelnormal3f)
9576                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9577                                         else
9578                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9579                                 }
9580                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9581                                 {
9582                                         if (rsurface.modelsvector3f)
9583                                         {
9584                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9585                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9586                                         }
9587                                         else
9588                                         {
9589                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9590                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9591                                         }
9592                                 }
9593                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9594                                 {
9595                                         if (rsurface.modellightmapcolor4f)
9596                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9597                                         else
9598                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9599                                 }
9600                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9601                                 {
9602                                         if (rsurface.modeltexcoordtexture2f)
9603                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9604                                         else
9605                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9606                                 }
9607                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9608                                 {
9609                                         if (rsurface.modeltexcoordlightmap2f)
9610                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9611                                         else
9612                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9613                                 }
9614                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9615                                 {
9616                                         if (rsurface.modelskeletalindex4ub)
9617                                         {
9618                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9619                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9620                                         }
9621                                         else
9622                                         {
9623                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9624                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9625                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9626                                                 for (j = 0;j < surfacenumvertices;j++)
9627                                                         ub[j*4] = 255;
9628                                         }
9629                                 }
9630                         }
9631                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9632                         numvertices += surfacenumvertices;
9633                         numtriangles += surfacenumtriangles;
9634                 }
9635
9636                 // generate a 16bit index array as well if possible
9637                 // (in general, dynamic batches fit)
9638                 if (numvertices <= 65536)
9639                 {
9640                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9641                         for (i = 0;i < numtriangles*3;i++)
9642                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9643                 }
9644
9645                 // since we've copied everything, the batch now starts at 0
9646                 rsurface.batchfirstvertex = 0;
9647                 rsurface.batchnumvertices = batchnumvertices;
9648                 rsurface.batchfirsttriangle = 0;
9649                 rsurface.batchnumtriangles = batchnumtriangles;
9650         }
9651
9652         // apply skeletal animation that would have been done in the vertex shader
9653         if (rsurface.batchskeletaltransform3x4)
9654         {
9655                 const unsigned char *si;
9656                 const unsigned char *sw;
9657                 const float *t[4];
9658                 const float *b = rsurface.batchskeletaltransform3x4;
9659                 float *vp, *vs, *vt, *vn;
9660                 float w[4];
9661                 float m[3][4], n[3][4];
9662                 float tp[3], ts[3], tt[3], tn[3];
9663                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9664                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9665                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9666                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9667                 si = rsurface.batchskeletalindex4ub;
9668                 sw = rsurface.batchskeletalweight4ub;
9669                 vp = rsurface.batchvertex3f;
9670                 vs = rsurface.batchsvector3f;
9671                 vt = rsurface.batchtvector3f;
9672                 vn = rsurface.batchnormal3f;
9673                 memset(m[0], 0, sizeof(m));
9674                 memset(n[0], 0, sizeof(n));
9675                 for (i = 0;i < batchnumvertices;i++)
9676                 {
9677                         t[0] = b + si[0]*12;
9678                         if (sw[0] == 255)
9679                         {
9680                                 // common case - only one matrix
9681                                 m[0][0] = t[0][ 0];
9682                                 m[0][1] = t[0][ 1];
9683                                 m[0][2] = t[0][ 2];
9684                                 m[0][3] = t[0][ 3];
9685                                 m[1][0] = t[0][ 4];
9686                                 m[1][1] = t[0][ 5];
9687                                 m[1][2] = t[0][ 6];
9688                                 m[1][3] = t[0][ 7];
9689                                 m[2][0] = t[0][ 8];
9690                                 m[2][1] = t[0][ 9];
9691                                 m[2][2] = t[0][10];
9692                                 m[2][3] = t[0][11];
9693                         }
9694                         else if (sw[2] + sw[3])
9695                         {
9696                                 // blend 4 matrices
9697                                 t[1] = b + si[1]*12;
9698                                 t[2] = b + si[2]*12;
9699                                 t[3] = b + si[3]*12;
9700                                 w[0] = sw[0] * (1.0f / 255.0f);
9701                                 w[1] = sw[1] * (1.0f / 255.0f);
9702                                 w[2] = sw[2] * (1.0f / 255.0f);
9703                                 w[3] = sw[3] * (1.0f / 255.0f);
9704                                 // blend the matrices
9705                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9706                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9707                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9708                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9709                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9710                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9711                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9712                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9713                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9714                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9715                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9716                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9717                         }
9718                         else
9719                         {
9720                                 // blend 2 matrices
9721                                 t[1] = b + si[1]*12;
9722                                 w[0] = sw[0] * (1.0f / 255.0f);
9723                                 w[1] = sw[1] * (1.0f / 255.0f);
9724                                 // blend the matrices
9725                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9726                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9727                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9728                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9729                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9730                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9731                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9732                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9733                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9734                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9735                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9736                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9737                         }
9738                         si += 4;
9739                         sw += 4;
9740                         // modify the vertex
9741                         VectorCopy(vp, tp);
9742                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9743                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9744                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9745                         vp += 3;
9746                         if (vn)
9747                         {
9748                                 // the normal transformation matrix is a set of cross products...
9749                                 CrossProduct(m[1], m[2], n[0]);
9750                                 CrossProduct(m[2], m[0], n[1]);
9751                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9752                                 VectorCopy(vn, tn);
9753                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9754                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9755                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9756                                 VectorNormalize(vn);
9757                                 vn += 3;
9758                                 if (vs)
9759                                 {
9760                                         VectorCopy(vs, ts);
9761                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9762                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9763                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9764                                         VectorNormalize(vs);
9765                                         vs += 3;
9766                                         VectorCopy(vt, tt);
9767                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9768                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9769                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9770                                         VectorNormalize(vt);
9771                                         vt += 3;
9772                                 }
9773                         }
9774                 }
9775                 rsurface.batchskeletaltransform3x4 = NULL;
9776                 rsurface.batchskeletalnumtransforms = 0;
9777         }
9778
9779         // q1bsp surfaces rendered in vertex color mode have to have colors
9780         // calculated based on lightstyles
9781         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9782         {
9783                 // generate color arrays for the surfaces in this list
9784                 int c[4];
9785                 int scale;
9786                 int size3;
9787                 const int *offsets;
9788                 const unsigned char *lm;
9789                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9790                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9791                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9792                 numvertices = 0;
9793                 for (i = 0;i < texturenumsurfaces;i++)
9794                 {
9795                         surface = texturesurfacelist[i];
9796                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9797                         surfacenumvertices = surface->num_vertices;
9798                         if (surface->lightmapinfo->samples)
9799                         {
9800                                 for (j = 0;j < surfacenumvertices;j++)
9801                                 {
9802                                         lm = surface->lightmapinfo->samples + offsets[j];
9803                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9804                                         VectorScale(lm, scale, c);
9805                                         if (surface->lightmapinfo->styles[1] != 255)
9806                                         {
9807                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9808                                                 lm += size3;
9809                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9810                                                 VectorMA(c, scale, lm, c);
9811                                                 if (surface->lightmapinfo->styles[2] != 255)
9812                                                 {
9813                                                         lm += size3;
9814                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9815                                                         VectorMA(c, scale, lm, c);
9816                                                         if (surface->lightmapinfo->styles[3] != 255)
9817                                                         {
9818                                                                 lm += size3;
9819                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9820                                                                 VectorMA(c, scale, lm, c);
9821                                                         }
9822                                                 }
9823                                         }
9824                                         c[0] >>= 7;
9825                                         c[1] >>= 7;
9826                                         c[2] >>= 7;
9827                                         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);
9828                                         numvertices++;
9829                                 }
9830                         }
9831                         else
9832                         {
9833                                 for (j = 0;j < surfacenumvertices;j++)
9834                                 {
9835                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9836                                         numvertices++;
9837                                 }
9838                         }
9839                 }
9840         }
9841
9842         // if vertices are deformed (sprite flares and things in maps, possibly
9843         // water waves, bulges and other deformations), modify the copied vertices
9844         // in place
9845         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9846         {
9847                 switch (deform->deform)
9848                 {
9849                 default:
9850                 case Q3DEFORM_PROJECTIONSHADOW:
9851                 case Q3DEFORM_TEXT0:
9852                 case Q3DEFORM_TEXT1:
9853                 case Q3DEFORM_TEXT2:
9854                 case Q3DEFORM_TEXT3:
9855                 case Q3DEFORM_TEXT4:
9856                 case Q3DEFORM_TEXT5:
9857                 case Q3DEFORM_TEXT6:
9858                 case Q3DEFORM_TEXT7:
9859                 case Q3DEFORM_NONE:
9860                         break;
9861                 case Q3DEFORM_AUTOSPRITE:
9862                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9863                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9864                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9865                         VectorNormalize(newforward);
9866                         VectorNormalize(newright);
9867                         VectorNormalize(newup);
9868 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9869 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9870 //                      rsurface.batchvertex3f_bufferoffset = 0;
9871 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9872 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9873 //                      rsurface.batchsvector3f_bufferoffset = 0;
9874 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9875 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9876 //                      rsurface.batchtvector3f_bufferoffset = 0;
9877 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9878 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9879 //                      rsurface.batchnormal3f_bufferoffset = 0;
9880                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9881                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9882                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9883                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9884                                 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);
9885                         // a single autosprite surface can contain multiple sprites...
9886                         for (j = 0;j < batchnumvertices - 3;j += 4)
9887                         {
9888                                 VectorClear(center);
9889                                 for (i = 0;i < 4;i++)
9890                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9891                                 VectorScale(center, 0.25f, center);
9892                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9893                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9894                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9895                                 for (i = 0;i < 4;i++)
9896                                 {
9897                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9898                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9899                                 }
9900                         }
9901                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9902                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9903                         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);
9904                         break;
9905                 case Q3DEFORM_AUTOSPRITE2:
9906                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9907                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9908                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9909                         VectorNormalize(newforward);
9910                         VectorNormalize(newright);
9911                         VectorNormalize(newup);
9912 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9913 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9914 //                      rsurface.batchvertex3f_bufferoffset = 0;
9915                         {
9916                                 const float *v1, *v2;
9917                                 vec3_t start, end;
9918                                 float f, l;
9919                                 struct
9920                                 {
9921                                         float length2;
9922                                         const float *v1;
9923                                         const float *v2;
9924                                 }
9925                                 shortest[2];
9926                                 memset(shortest, 0, sizeof(shortest));
9927                                 // a single autosprite surface can contain multiple sprites...
9928                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9929                                 {
9930                                         VectorClear(center);
9931                                         for (i = 0;i < 4;i++)
9932                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9933                                         VectorScale(center, 0.25f, center);
9934                                         // find the two shortest edges, then use them to define the
9935                                         // axis vectors for rotating around the central axis
9936                                         for (i = 0;i < 6;i++)
9937                                         {
9938                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9939                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9940                                                 l = VectorDistance2(v1, v2);
9941                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9942                                                 if (v1[2] != v2[2])
9943                                                         l += (1.0f / 1024.0f);
9944                                                 if (shortest[0].length2 > l || i == 0)
9945                                                 {
9946                                                         shortest[1] = shortest[0];
9947                                                         shortest[0].length2 = l;
9948                                                         shortest[0].v1 = v1;
9949                                                         shortest[0].v2 = v2;
9950                                                 }
9951                                                 else if (shortest[1].length2 > l || i == 1)
9952                                                 {
9953                                                         shortest[1].length2 = l;
9954                                                         shortest[1].v1 = v1;
9955                                                         shortest[1].v2 = v2;
9956                                                 }
9957                                         }
9958                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9959                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9960                                         // this calculates the right vector from the shortest edge
9961                                         // and the up vector from the edge midpoints
9962                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9963                                         VectorNormalize(right);
9964                                         VectorSubtract(end, start, up);
9965                                         VectorNormalize(up);
9966                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9967                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9968                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9969                                         VectorNegate(forward, forward);
9970                                         VectorReflect(forward, 0, up, forward);
9971                                         VectorNormalize(forward);
9972                                         CrossProduct(up, forward, newright);
9973                                         VectorNormalize(newright);
9974                                         // rotate the quad around the up axis vector, this is made
9975                                         // especially easy by the fact we know the quad is flat,
9976                                         // so we only have to subtract the center position and
9977                                         // measure distance along the right vector, and then
9978                                         // multiply that by the newright vector and add back the
9979                                         // center position
9980                                         // we also need to subtract the old position to undo the
9981                                         // displacement from the center, which we do with a
9982                                         // DotProduct, the subtraction/addition of center is also
9983                                         // optimized into DotProducts here
9984                                         l = DotProduct(right, center);
9985                                         for (i = 0;i < 4;i++)
9986                                         {
9987                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9988                                                 f = DotProduct(right, v1) - l;
9989                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9990                                         }
9991                                 }
9992                         }
9993                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9994                         {
9995 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9996 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9997 //                              rsurface.batchnormal3f_bufferoffset = 0;
9998                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9999                         }
10000                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10001                         {
10002 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10003 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10004 //                              rsurface.batchsvector3f_bufferoffset = 0;
10005 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10006 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10007 //                              rsurface.batchtvector3f_bufferoffset = 0;
10008                                 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);
10009                         }
10010                         break;
10011                 case Q3DEFORM_NORMAL:
10012                         // deform the normals to make reflections wavey
10013                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10014                         rsurface.batchnormal3f_vertexbuffer = NULL;
10015                         rsurface.batchnormal3f_bufferoffset = 0;
10016                         for (j = 0;j < batchnumvertices;j++)
10017                         {
10018                                 float vertex[3];
10019                                 float *normal = rsurface.batchnormal3f + 3*j;
10020                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10021                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10022                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10023                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10024                                 VectorNormalize(normal);
10025                         }
10026                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10027                         {
10028 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10029 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10030 //                              rsurface.batchsvector3f_bufferoffset = 0;
10031 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10032 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10033 //                              rsurface.batchtvector3f_bufferoffset = 0;
10034                                 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);
10035                         }
10036                         break;
10037                 case Q3DEFORM_WAVE:
10038                         // deform vertex array to make wavey water and flags and such
10039                         waveparms[0] = deform->waveparms[0];
10040                         waveparms[1] = deform->waveparms[1];
10041                         waveparms[2] = deform->waveparms[2];
10042                         waveparms[3] = deform->waveparms[3];
10043                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10044                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10045                         // this is how a divisor of vertex influence on deformation
10046                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10047                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10048 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10049 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10050 //                      rsurface.batchvertex3f_bufferoffset = 0;
10051 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10052 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10053 //                      rsurface.batchnormal3f_bufferoffset = 0;
10054                         for (j = 0;j < batchnumvertices;j++)
10055                         {
10056                                 // if the wavefunc depends on time, evaluate it per-vertex
10057                                 if (waveparms[3])
10058                                 {
10059                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10060                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10061                                 }
10062                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10063                         }
10064                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10065                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10066                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10067                         {
10068 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10069 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10070 //                              rsurface.batchsvector3f_bufferoffset = 0;
10071 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10072 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10073 //                              rsurface.batchtvector3f_bufferoffset = 0;
10074                                 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);
10075                         }
10076                         break;
10077                 case Q3DEFORM_BULGE:
10078                         // deform vertex array to make the surface have moving bulges
10079 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10080 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10081 //                      rsurface.batchvertex3f_bufferoffset = 0;
10082 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10083 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10084 //                      rsurface.batchnormal3f_bufferoffset = 0;
10085                         for (j = 0;j < batchnumvertices;j++)
10086                         {
10087                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10088                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10089                         }
10090                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10091                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10092                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10093                         {
10094 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10095 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10096 //                              rsurface.batchsvector3f_bufferoffset = 0;
10097 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10098 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10099 //                              rsurface.batchtvector3f_bufferoffset = 0;
10100                                 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);
10101                         }
10102                         break;
10103                 case Q3DEFORM_MOVE:
10104                         // deform vertex array
10105                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10106                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10107                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10108                         VectorScale(deform->parms, scale, waveparms);
10109 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10110 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10111 //                      rsurface.batchvertex3f_bufferoffset = 0;
10112                         for (j = 0;j < batchnumvertices;j++)
10113                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10114                         break;
10115                 }
10116         }
10117
10118         if (rsurface.batchtexcoordtexture2f)
10119         {
10120         // generate texcoords based on the chosen texcoord source
10121                 switch(rsurface.texture->tcgen.tcgen)
10122                 {
10123                 default:
10124                 case Q3TCGEN_TEXTURE:
10125                         break;
10126                 case Q3TCGEN_LIGHTMAP:
10127         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10128         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10129         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10130                         if (rsurface.batchtexcoordlightmap2f)
10131                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10132                         break;
10133                 case Q3TCGEN_VECTOR:
10134         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10135         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10136         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10137                         for (j = 0;j < batchnumvertices;j++)
10138                         {
10139                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10140                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10141                         }
10142                         break;
10143                 case Q3TCGEN_ENVIRONMENT:
10144                         // make environment reflections using a spheremap
10145                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10146                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10147                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10148                         for (j = 0;j < batchnumvertices;j++)
10149                         {
10150                                 // identical to Q3A's method, but executed in worldspace so
10151                                 // carried models can be shiny too
10152
10153                                 float viewer[3], d, reflected[3], worldreflected[3];
10154
10155                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10156                                 // VectorNormalize(viewer);
10157
10158                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10159
10160                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10161                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10162                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10163                                 // note: this is proportinal to viewer, so we can normalize later
10164
10165                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10166                                 VectorNormalize(worldreflected);
10167
10168                                 // note: this sphere map only uses world x and z!
10169                                 // so positive and negative y will LOOK THE SAME.
10170                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10171                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10172                         }
10173                         break;
10174                 }
10175                 // the only tcmod that needs software vertex processing is turbulent, so
10176                 // check for it here and apply the changes if needed
10177                 // and we only support that as the first one
10178                 // (handling a mixture of turbulent and other tcmods would be problematic
10179                 //  without punting it entirely to a software path)
10180                 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10181                 {
10182                         amplitude = rsurface.texture->tcmods[0].parms[1];
10183                         animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10184         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10185         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10186         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10187                         for (j = 0;j < batchnumvertices;j++)
10188                         {
10189                                 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);
10190                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10191                         }
10192                 }
10193         }
10194
10195         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10196         {
10197                 // convert the modified arrays to vertex structs
10198 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10199 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10200 //              rsurface.batchvertexmesh_bufferoffset = 0;
10201                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10202                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10203                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10204                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10205                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10206                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10207                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10208                 {
10209                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10210                         {
10211                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10212                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10213                         }
10214                 }
10215                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10216                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10217                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10218                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10219                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10220                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10221                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10222                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10223                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10224                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10225                 {
10226                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10227                         {
10228                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10229                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10230                         }
10231                 }
10232         }
10233
10234         // upload buffer data for the dynamic batch
10235         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10236         {
10237                 if (rsurface.batchvertexmesh)
10238                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10239                 else
10240                 {
10241                         if (rsurface.batchvertex3f)
10242                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10243                         if (rsurface.batchsvector3f)
10244                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10245                         if (rsurface.batchtvector3f)
10246                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10247                         if (rsurface.batchnormal3f)
10248                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10249                         if (rsurface.batchlightmapcolor4f)
10250                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10251                         if (rsurface.batchtexcoordtexture2f)
10252                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10253                         if (rsurface.batchtexcoordlightmap2f)
10254                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10255                         if (rsurface.batchskeletalindex4ub)
10256                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10257                         if (rsurface.batchskeletalweight4ub)
10258                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10259                 }
10260                 if (rsurface.batchelement3s)
10261                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10262                 else if (rsurface.batchelement3i)
10263                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10264         }
10265 }
10266
10267 void RSurf_DrawBatch(void)
10268 {
10269         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10270         // through the pipeline, killing it earlier in the pipeline would have
10271         // per-surface overhead rather than per-batch overhead, so it's best to
10272         // reject it here, before it hits glDraw.
10273         if (rsurface.batchnumtriangles == 0)
10274                 return;
10275 #if 0
10276         // batch debugging code
10277         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10278         {
10279                 int i;
10280                 int j;
10281                 int c;
10282                 const int *e;
10283                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10284                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10285                 {
10286                         c = e[i];
10287                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10288                         {
10289                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10290                                 {
10291                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10292                                                 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);
10293                                         break;
10294                                 }
10295                         }
10296                 }
10297         }
10298 #endif
10299         if (rsurface.batchmultidraw)
10300         {
10301                 // issue multiple draws rather than copying index data
10302                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10303                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10304                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10305                 for (i = 0;i < numsurfaces;)
10306                 {
10307                         // combine consecutive surfaces as one draw
10308                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10309                                 if (surfacelist[j] != surfacelist[k] + 1)
10310                                         break;
10311                         firstvertex = surfacelist[i]->num_firstvertex;
10312                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10313                         firsttriangle = surfacelist[i]->num_firsttriangle;
10314                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10315                         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);
10316                         i = j;
10317                 }
10318         }
10319         else
10320         {
10321                 // there is only one consecutive run of index data (may have been combined)
10322                 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);
10323         }
10324 }
10325
10326 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10327 {
10328         // pick the closest matching water plane
10329         int planeindex, vertexindex, bestplaneindex = -1;
10330         float d, bestd;
10331         vec3_t vert;
10332         const float *v;
10333         r_waterstate_waterplane_t *p;
10334         qboolean prepared = false;
10335         bestd = 0;
10336         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10337         {
10338                 if(p->camera_entity != rsurface.texture->camera_entity)
10339                         continue;
10340                 d = 0;
10341                 if(!prepared)
10342                 {
10343                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10344                         prepared = true;
10345                         if(rsurface.batchnumvertices == 0)
10346                                 break;
10347                 }
10348                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10349                 {
10350                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10351                         d += fabs(PlaneDiff(vert, &p->plane));
10352                 }
10353                 if (bestd > d || bestplaneindex < 0)
10354                 {
10355                         bestd = d;
10356                         bestplaneindex = planeindex;
10357                 }
10358         }
10359         return bestplaneindex;
10360         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10361         // this situation though, as it might be better to render single larger
10362         // batches with useless stuff (backface culled for example) than to
10363         // render multiple smaller batches
10364 }
10365
10366 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10367 {
10368         int i;
10369         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10370         rsurface.passcolor4f_vertexbuffer = 0;
10371         rsurface.passcolor4f_bufferoffset = 0;
10372         for (i = 0;i < rsurface.batchnumvertices;i++)
10373                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10374 }
10375
10376 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10377 {
10378         int i;
10379         float f;
10380         const float *v;
10381         const float *c;
10382         float *c2;
10383         if (rsurface.passcolor4f)
10384         {
10385                 // generate color arrays
10386                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10387                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10388                 rsurface.passcolor4f_vertexbuffer = 0;
10389                 rsurface.passcolor4f_bufferoffset = 0;
10390                 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)
10391                 {
10392                         f = RSurf_FogVertex(v);
10393                         c2[0] = c[0] * f;
10394                         c2[1] = c[1] * f;
10395                         c2[2] = c[2] * f;
10396                         c2[3] = c[3];
10397                 }
10398         }
10399         else
10400         {
10401                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10402                 rsurface.passcolor4f_vertexbuffer = 0;
10403                 rsurface.passcolor4f_bufferoffset = 0;
10404                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10405                 {
10406                         f = RSurf_FogVertex(v);
10407                         c2[0] = f;
10408                         c2[1] = f;
10409                         c2[2] = f;
10410                         c2[3] = 1;
10411                 }
10412         }
10413 }
10414
10415 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10416 {
10417         int i;
10418         float f;
10419         const float *v;
10420         const float *c;
10421         float *c2;
10422         if (!rsurface.passcolor4f)
10423                 return;
10424         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10425         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10426         rsurface.passcolor4f_vertexbuffer = 0;
10427         rsurface.passcolor4f_bufferoffset = 0;
10428         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)
10429         {
10430                 f = RSurf_FogVertex(v);
10431                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10432                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10433                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10434                 c2[3] = c[3];
10435         }
10436 }
10437
10438 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10439 {
10440         int i;
10441         const float *c;
10442         float *c2;
10443         if (!rsurface.passcolor4f)
10444                 return;
10445         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10446         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10447         rsurface.passcolor4f_vertexbuffer = 0;
10448         rsurface.passcolor4f_bufferoffset = 0;
10449         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10450         {
10451                 c2[0] = c[0] * r;
10452                 c2[1] = c[1] * g;
10453                 c2[2] = c[2] * b;
10454                 c2[3] = c[3] * a;
10455         }
10456 }
10457
10458 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10459 {
10460         int i;
10461         const float *c;
10462         float *c2;
10463         if (!rsurface.passcolor4f)
10464                 return;
10465         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10466         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10467         rsurface.passcolor4f_vertexbuffer = 0;
10468         rsurface.passcolor4f_bufferoffset = 0;
10469         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10470         {
10471                 c2[0] = c[0] + r_refdef.scene.ambient;
10472                 c2[1] = c[1] + r_refdef.scene.ambient;
10473                 c2[2] = c[2] + r_refdef.scene.ambient;
10474                 c2[3] = c[3];
10475         }
10476 }
10477
10478 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10479 {
10480         // TODO: optimize
10481         rsurface.passcolor4f = NULL;
10482         rsurface.passcolor4f_vertexbuffer = 0;
10483         rsurface.passcolor4f_bufferoffset = 0;
10484         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10485         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10486         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10487         GL_Color(r, g, b, a);
10488         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10489         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10490         R_Mesh_TexMatrix(0, NULL);
10491         RSurf_DrawBatch();
10492 }
10493
10494 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10495 {
10496         // TODO: optimize applyfog && applycolor case
10497         // just apply fog if necessary, and tint the fog color array if necessary
10498         rsurface.passcolor4f = NULL;
10499         rsurface.passcolor4f_vertexbuffer = 0;
10500         rsurface.passcolor4f_bufferoffset = 0;
10501         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10502         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10503         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10504         GL_Color(r, g, b, a);
10505         RSurf_DrawBatch();
10506 }
10507
10508 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10509 {
10510         // TODO: optimize
10511         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10512         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10513         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10514         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10515         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10516         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10517         GL_Color(r, g, b, a);
10518         RSurf_DrawBatch();
10519 }
10520
10521 static void RSurf_DrawBatch_GL11_ClampColor(void)
10522 {
10523         int i;
10524         const float *c1;
10525         float *c2;
10526         if (!rsurface.passcolor4f)
10527                 return;
10528         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10529         {
10530                 c2[0] = bound(0.0f, c1[0], 1.0f);
10531                 c2[1] = bound(0.0f, c1[1], 1.0f);
10532                 c2[2] = bound(0.0f, c1[2], 1.0f);
10533                 c2[3] = bound(0.0f, c1[3], 1.0f);
10534         }
10535 }
10536
10537 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10538 {
10539         int i;
10540         float f;
10541         const float *v;
10542         const float *n;
10543         float *c;
10544         //vec3_t eyedir;
10545
10546         // fake shading
10547         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10548         rsurface.passcolor4f_vertexbuffer = 0;
10549         rsurface.passcolor4f_bufferoffset = 0;
10550         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)
10551         {
10552                 f = -DotProduct(r_refdef.view.forward, n);
10553                 f = max(0, f);
10554                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10555                 f *= r_refdef.lightmapintensity;
10556                 Vector4Set(c, f, f, f, 1);
10557         }
10558 }
10559
10560 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10561 {
10562         RSurf_DrawBatch_GL11_ApplyFakeLight();
10563         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10564         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10565         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10566         GL_Color(r, g, b, a);
10567         RSurf_DrawBatch();
10568 }
10569
10570 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10571 {
10572         int i;
10573         float f;
10574         float alpha;
10575         const float *v;
10576         const float *n;
10577         float *c;
10578         vec3_t ambientcolor;
10579         vec3_t diffusecolor;
10580         vec3_t lightdir;
10581         // TODO: optimize
10582         // model lighting
10583         VectorCopy(rsurface.modellight_lightdir, lightdir);
10584         f = 0.5f * r_refdef.lightmapintensity;
10585         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10586         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10587         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10588         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10589         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10590         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10591         alpha = *a;
10592         if (VectorLength2(diffusecolor) > 0)
10593         {
10594                 // q3-style directional shading
10595                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10596                 rsurface.passcolor4f_vertexbuffer = 0;
10597                 rsurface.passcolor4f_bufferoffset = 0;
10598                 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)
10599                 {
10600                         if ((f = DotProduct(n, lightdir)) > 0)
10601                                 VectorMA(ambientcolor, f, diffusecolor, c);
10602                         else
10603                                 VectorCopy(ambientcolor, c);
10604                         c[3] = alpha;
10605                 }
10606                 *r = 1;
10607                 *g = 1;
10608                 *b = 1;
10609                 *a = 1;
10610                 *applycolor = false;
10611         }
10612         else
10613         {
10614                 *r = ambientcolor[0];
10615                 *g = ambientcolor[1];
10616                 *b = ambientcolor[2];
10617                 rsurface.passcolor4f = NULL;
10618                 rsurface.passcolor4f_vertexbuffer = 0;
10619                 rsurface.passcolor4f_bufferoffset = 0;
10620         }
10621 }
10622
10623 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10624 {
10625         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10626         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10627         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10628         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10629         GL_Color(r, g, b, a);
10630         RSurf_DrawBatch();
10631 }
10632
10633 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10634 {
10635         int i;
10636         float f;
10637         const float *v;
10638         float *c;
10639
10640         // fake shading
10641         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10642         rsurface.passcolor4f_vertexbuffer = 0;
10643         rsurface.passcolor4f_bufferoffset = 0;
10644
10645         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10646         {
10647                 f = 1 - RSurf_FogVertex(v);
10648                 c[0] = r;
10649                 c[1] = g;
10650                 c[2] = b;
10651                 c[3] = f * a;
10652         }
10653 }
10654
10655 void RSurf_SetupDepthAndCulling(void)
10656 {
10657         // submodels are biased to avoid z-fighting with world surfaces that they
10658         // may be exactly overlapping (avoids z-fighting artifacts on certain
10659         // doors and things in Quake maps)
10660         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10661         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10662         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10663         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10664 }
10665
10666 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10667 {
10668         // transparent sky would be ridiculous
10669         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10670                 return;
10671         R_SetupShader_Generic_NoTexture(false, false);
10672         skyrenderlater = true;
10673         RSurf_SetupDepthAndCulling();
10674         GL_DepthMask(true);
10675         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10676         // skymasking on them, and Quake3 never did sky masking (unlike
10677         // software Quake and software Quake2), so disable the sky masking
10678         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10679         // and skymasking also looks very bad when noclipping outside the
10680         // level, so don't use it then either.
10681         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10682         {
10683                 R_Mesh_ResetTextureState();
10684                 if (skyrendermasked)
10685                 {
10686                         R_SetupShader_DepthOrShadow(false, false, false);
10687                         // depth-only (masking)
10688                         GL_ColorMask(0,0,0,0);
10689                         // just to make sure that braindead drivers don't draw
10690                         // anything despite that colormask...
10691                         GL_BlendFunc(GL_ZERO, GL_ONE);
10692                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10693                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10694                 }
10695                 else
10696                 {
10697                         R_SetupShader_Generic_NoTexture(false, false);
10698                         // fog sky
10699                         GL_BlendFunc(GL_ONE, GL_ZERO);
10700                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10701                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10702                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10703                 }
10704                 RSurf_DrawBatch();
10705                 if (skyrendermasked)
10706                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10707         }
10708         R_Mesh_ResetTextureState();
10709         GL_Color(1, 1, 1, 1);
10710 }
10711
10712 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10713 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10714 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10715 {
10716         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10717                 return;
10718         if (prepass)
10719         {
10720                 // render screenspace normalmap to texture
10721                 GL_DepthMask(true);
10722                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10723                 RSurf_DrawBatch();
10724                 return;
10725         }
10726
10727         // bind lightmap texture
10728
10729         // water/refraction/reflection/camera surfaces have to be handled specially
10730         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10731         {
10732                 int start, end, startplaneindex;
10733                 for (start = 0;start < texturenumsurfaces;start = end)
10734                 {
10735                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10736                         if(startplaneindex < 0)
10737                         {
10738                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10739                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10740                                 end = start + 1;
10741                                 continue;
10742                         }
10743                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10744                                 ;
10745                         // now that we have a batch using the same planeindex, render it
10746                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10747                         {
10748                                 // render water or distortion background
10749                                 GL_DepthMask(true);
10750                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10751                                 RSurf_DrawBatch();
10752                                 // blend surface on top
10753                                 GL_DepthMask(false);
10754                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10755                                 RSurf_DrawBatch();
10756                         }
10757                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10758                         {
10759                                 // render surface with reflection texture as input
10760                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10761                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10762                                 RSurf_DrawBatch();
10763                         }
10764                 }
10765                 return;
10766         }
10767
10768         // render surface batch normally
10769         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10770         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10771         RSurf_DrawBatch();
10772 }
10773
10774 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10775 {
10776         // OpenGL 1.3 path - anything not completely ancient
10777         qboolean applycolor;
10778         qboolean applyfog;
10779         int layerindex;
10780         const texturelayer_t *layer;
10781         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10782         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10783
10784         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10785         {
10786                 vec4_t layercolor;
10787                 int layertexrgbscale;
10788                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10789                 {
10790                         if (layerindex == 0)
10791                                 GL_AlphaTest(true);
10792                         else
10793                         {
10794                                 GL_AlphaTest(false);
10795                                 GL_DepthFunc(GL_EQUAL);
10796                         }
10797                 }
10798                 GL_DepthMask(layer->depthmask && writedepth);
10799                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10800                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10801                 {
10802                         layertexrgbscale = 4;
10803                         VectorScale(layer->color, 0.25f, layercolor);
10804                 }
10805                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10806                 {
10807                         layertexrgbscale = 2;
10808                         VectorScale(layer->color, 0.5f, layercolor);
10809                 }
10810                 else
10811                 {
10812                         layertexrgbscale = 1;
10813                         VectorScale(layer->color, 1.0f, layercolor);
10814                 }
10815                 layercolor[3] = layer->color[3];
10816                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10817                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10818                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10819                 switch (layer->type)
10820                 {
10821                 case TEXTURELAYERTYPE_LITTEXTURE:
10822                         // single-pass lightmapped texture with 2x rgbscale
10823                         R_Mesh_TexBind(0, r_texture_white);
10824                         R_Mesh_TexMatrix(0, NULL);
10825                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10826                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10827                         R_Mesh_TexBind(1, layer->texture);
10828                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10829                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10830                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10831                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10832                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10833                         else if (FAKELIGHT_ENABLED)
10834                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10835                         else if (rsurface.uselightmaptexture)
10836                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10837                         else
10838                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10839                         break;
10840                 case TEXTURELAYERTYPE_TEXTURE:
10841                         // singletexture unlit texture with transparency support
10842                         R_Mesh_TexBind(0, layer->texture);
10843                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10844                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10845                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10846                         R_Mesh_TexBind(1, 0);
10847                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10848                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10849                         break;
10850                 case TEXTURELAYERTYPE_FOG:
10851                         // singletexture fogging
10852                         if (layer->texture)
10853                         {
10854                                 R_Mesh_TexBind(0, layer->texture);
10855                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10856                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10857                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10858                         }
10859                         else
10860                         {
10861                                 R_Mesh_TexBind(0, 0);
10862                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10863                         }
10864                         R_Mesh_TexBind(1, 0);
10865                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10866                         // generate a color array for the fog pass
10867                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10868                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10869                         RSurf_DrawBatch();
10870                         break;
10871                 default:
10872                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10873                 }
10874         }
10875         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10876         {
10877                 GL_DepthFunc(GL_LEQUAL);
10878                 GL_AlphaTest(false);
10879         }
10880 }
10881
10882 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10883 {
10884         // OpenGL 1.1 - crusty old voodoo path
10885         qboolean applyfog;
10886         int layerindex;
10887         const texturelayer_t *layer;
10888         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10889         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10890
10891         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10892         {
10893                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10894                 {
10895                         if (layerindex == 0)
10896                                 GL_AlphaTest(true);
10897                         else
10898                         {
10899                                 GL_AlphaTest(false);
10900                                 GL_DepthFunc(GL_EQUAL);
10901                         }
10902                 }
10903                 GL_DepthMask(layer->depthmask && writedepth);
10904                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10905                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10906                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10907                 switch (layer->type)
10908                 {
10909                 case TEXTURELAYERTYPE_LITTEXTURE:
10910                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10911                         {
10912                                 // two-pass lit texture with 2x rgbscale
10913                                 // first the lightmap pass
10914                                 R_Mesh_TexBind(0, r_texture_white);
10915                                 R_Mesh_TexMatrix(0, NULL);
10916                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10917                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10918                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10919                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10920                                 else if (FAKELIGHT_ENABLED)
10921                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10922                                 else if (rsurface.uselightmaptexture)
10923                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10924                                 else
10925                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10926                                 // then apply the texture to it
10927                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10928                                 R_Mesh_TexBind(0, layer->texture);
10929                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10930                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10931                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10932                                 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);
10933                         }
10934                         else
10935                         {
10936                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10937                                 R_Mesh_TexBind(0, layer->texture);
10938                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10939                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10940                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10941                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10942                                         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);
10943                                 else if (FAKELIGHT_ENABLED)
10944                                         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);
10945                                 else
10946                                         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);
10947                         }
10948                         break;
10949                 case TEXTURELAYERTYPE_TEXTURE:
10950                         // singletexture unlit texture with transparency support
10951                         R_Mesh_TexBind(0, layer->texture);
10952                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10953                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10954                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10955                         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);
10956                         break;
10957                 case TEXTURELAYERTYPE_FOG:
10958                         // singletexture fogging
10959                         if (layer->texture)
10960                         {
10961                                 R_Mesh_TexBind(0, layer->texture);
10962                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10963                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10964                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10965                         }
10966                         else
10967                         {
10968                                 R_Mesh_TexBind(0, 0);
10969                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10970                         }
10971                         // generate a color array for the fog pass
10972                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10973                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10974                         RSurf_DrawBatch();
10975                         break;
10976                 default:
10977                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10978                 }
10979         }
10980         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10981         {
10982                 GL_DepthFunc(GL_LEQUAL);
10983                 GL_AlphaTest(false);
10984         }
10985 }
10986
10987 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10988 {
10989         int vi;
10990         int j;
10991         r_vertexgeneric_t *batchvertex;
10992         float c[4];
10993
10994 //      R_Mesh_ResetTextureState();
10995         R_SetupShader_Generic_NoTexture(false, false);
10996
10997         if(rsurface.texture && rsurface.texture->currentskinframe)
10998         {
10999                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11000                 c[3] *= rsurface.texture->currentalpha;
11001         }
11002         else
11003         {
11004                 c[0] = 1;
11005                 c[1] = 0;
11006                 c[2] = 1;
11007                 c[3] = 1;
11008         }
11009
11010         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11011         {
11012                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11013                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11014                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11015         }
11016
11017         // brighten it up (as texture value 127 means "unlit")
11018         c[0] *= 2 * r_refdef.view.colorscale;
11019         c[1] *= 2 * r_refdef.view.colorscale;
11020         c[2] *= 2 * r_refdef.view.colorscale;
11021
11022         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11023                 c[3] *= r_wateralpha.value;
11024
11025         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11026         {
11027                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11028                 GL_DepthMask(false);
11029         }
11030         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11031         {
11032                 GL_BlendFunc(GL_ONE, GL_ONE);
11033                 GL_DepthMask(false);
11034         }
11035         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11036         {
11037                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11038                 GL_DepthMask(false);
11039         }
11040         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11041         {
11042                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11043                 GL_DepthMask(false);
11044         }
11045         else
11046         {
11047                 GL_BlendFunc(GL_ONE, GL_ZERO);
11048                 GL_DepthMask(writedepth);
11049         }
11050
11051         if (r_showsurfaces.integer == 3)
11052         {
11053                 rsurface.passcolor4f = NULL;
11054
11055                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11056                 {
11057                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11058
11059                         rsurface.passcolor4f = NULL;
11060                         rsurface.passcolor4f_vertexbuffer = 0;
11061                         rsurface.passcolor4f_bufferoffset = 0;
11062                 }
11063                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11064                 {
11065                         qboolean applycolor = true;
11066                         float one = 1.0;
11067
11068                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11069
11070                         r_refdef.lightmapintensity = 1;
11071                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11072                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11073                 }
11074                 else if (FAKELIGHT_ENABLED)
11075                 {
11076                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11077
11078                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11079                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11080                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11081                 }
11082                 else
11083                 {
11084                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11085
11086                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11087                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11088                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11089                 }
11090
11091                 if(!rsurface.passcolor4f)
11092                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11093
11094                 RSurf_DrawBatch_GL11_ApplyAmbient();
11095                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11096                 if(r_refdef.fogenabled)
11097                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11098                 RSurf_DrawBatch_GL11_ClampColor();
11099
11100                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11101                 R_SetupShader_Generic_NoTexture(false, false);
11102                 RSurf_DrawBatch();
11103         }
11104         else if (!r_refdef.view.showdebug)
11105         {
11106                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11107                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11108                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11109                 {
11110                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11111                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11112                 }
11113                 R_Mesh_PrepareVertices_Generic_Unlock();
11114                 RSurf_DrawBatch();
11115         }
11116         else if (r_showsurfaces.integer == 4)
11117         {
11118                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11119                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11120                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11121                 {
11122                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11123                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11124                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11125                 }
11126                 R_Mesh_PrepareVertices_Generic_Unlock();
11127                 RSurf_DrawBatch();
11128         }
11129         else if (r_showsurfaces.integer == 2)
11130         {
11131                 const int *e;
11132                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11133                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11134                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11135                 {
11136                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11137                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11138                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11139                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11140                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11141                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11142                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11143                 }
11144                 R_Mesh_PrepareVertices_Generic_Unlock();
11145                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11146         }
11147         else
11148         {
11149                 int texturesurfaceindex;
11150                 int k;
11151                 const msurface_t *surface;
11152                 float surfacecolor4f[4];
11153                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11154                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11155                 vi = 0;
11156                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11157                 {
11158                         surface = texturesurfacelist[texturesurfaceindex];
11159                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11160                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11161                         for (j = 0;j < surface->num_vertices;j++)
11162                         {
11163                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11164                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11165                                 vi++;
11166                         }
11167                 }
11168                 R_Mesh_PrepareVertices_Generic_Unlock();
11169                 RSurf_DrawBatch();
11170         }
11171 }
11172
11173 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11174 {
11175         CHECKGLERROR
11176         RSurf_SetupDepthAndCulling();
11177         if (r_showsurfaces.integer)
11178         {
11179                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11180                 return;
11181         }
11182         switch (vid.renderpath)
11183         {
11184         case RENDERPATH_GL20:
11185         case RENDERPATH_D3D9:
11186         case RENDERPATH_D3D10:
11187         case RENDERPATH_D3D11:
11188         case RENDERPATH_SOFT:
11189         case RENDERPATH_GLES2:
11190                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11191                 break;
11192         case RENDERPATH_GL13:
11193         case RENDERPATH_GLES1:
11194                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11195                 break;
11196         case RENDERPATH_GL11:
11197                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11198                 break;
11199         }
11200         CHECKGLERROR
11201 }
11202
11203 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11204 {
11205         CHECKGLERROR
11206         RSurf_SetupDepthAndCulling();
11207         if (r_showsurfaces.integer)
11208         {
11209                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11210                 return;
11211         }
11212         switch (vid.renderpath)
11213         {
11214         case RENDERPATH_GL20:
11215         case RENDERPATH_D3D9:
11216         case RENDERPATH_D3D10:
11217         case RENDERPATH_D3D11:
11218         case RENDERPATH_SOFT:
11219         case RENDERPATH_GLES2:
11220                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11221                 break;
11222         case RENDERPATH_GL13:
11223         case RENDERPATH_GLES1:
11224                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11225                 break;
11226         case RENDERPATH_GL11:
11227                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11228                 break;
11229         }
11230         CHECKGLERROR
11231 }
11232
11233 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11234 {
11235         int i, j;
11236         int texturenumsurfaces, endsurface;
11237         texture_t *texture;
11238         const msurface_t *surface;
11239         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11240
11241         // if the model is static it doesn't matter what value we give for
11242         // wantnormals and wanttangents, so this logic uses only rules applicable
11243         // to a model, knowing that they are meaningless otherwise
11244         if (ent == r_refdef.scene.worldentity)
11245                 RSurf_ActiveWorldEntity();
11246         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11247                 RSurf_ActiveModelEntity(ent, false, false, false);
11248         else
11249         {
11250                 switch (vid.renderpath)
11251                 {
11252                 case RENDERPATH_GL20:
11253                 case RENDERPATH_D3D9:
11254                 case RENDERPATH_D3D10:
11255                 case RENDERPATH_D3D11:
11256                 case RENDERPATH_SOFT:
11257                 case RENDERPATH_GLES2:
11258                         RSurf_ActiveModelEntity(ent, true, true, false);
11259                         break;
11260                 case RENDERPATH_GL11:
11261                 case RENDERPATH_GL13:
11262                 case RENDERPATH_GLES1:
11263                         RSurf_ActiveModelEntity(ent, true, false, false);
11264                         break;
11265                 }
11266         }
11267
11268         if (r_transparentdepthmasking.integer)
11269         {
11270                 qboolean setup = false;
11271                 for (i = 0;i < numsurfaces;i = j)
11272                 {
11273                         j = i + 1;
11274                         surface = rsurface.modelsurfaces + surfacelist[i];
11275                         texture = surface->texture;
11276                         rsurface.texture = R_GetCurrentTexture(texture);
11277                         rsurface.lightmaptexture = NULL;
11278                         rsurface.deluxemaptexture = NULL;
11279                         rsurface.uselightmaptexture = false;
11280                         // scan ahead until we find a different texture
11281                         endsurface = min(i + 1024, numsurfaces);
11282                         texturenumsurfaces = 0;
11283                         texturesurfacelist[texturenumsurfaces++] = surface;
11284                         for (;j < endsurface;j++)
11285                         {
11286                                 surface = rsurface.modelsurfaces + surfacelist[j];
11287                                 if (texture != surface->texture)
11288                                         break;
11289                                 texturesurfacelist[texturenumsurfaces++] = surface;
11290                         }
11291                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11292                                 continue;
11293                         // render the range of surfaces as depth
11294                         if (!setup)
11295                         {
11296                                 setup = true;
11297                                 GL_ColorMask(0,0,0,0);
11298                                 GL_Color(1,1,1,1);
11299                                 GL_DepthTest(true);
11300                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11301                                 GL_DepthMask(true);
11302 //                              R_Mesh_ResetTextureState();
11303                         }
11304                         RSurf_SetupDepthAndCulling();
11305                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11306                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11307                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11308                         RSurf_DrawBatch();
11309                 }
11310                 if (setup)
11311                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11312         }
11313
11314         for (i = 0;i < numsurfaces;i = j)
11315         {
11316                 j = i + 1;
11317                 surface = rsurface.modelsurfaces + surfacelist[i];
11318                 texture = surface->texture;
11319                 rsurface.texture = R_GetCurrentTexture(texture);
11320                 // scan ahead until we find a different texture
11321                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11322                 texturenumsurfaces = 0;
11323                 texturesurfacelist[texturenumsurfaces++] = surface;
11324                 if(FAKELIGHT_ENABLED)
11325                 {
11326                         rsurface.lightmaptexture = NULL;
11327                         rsurface.deluxemaptexture = NULL;
11328                         rsurface.uselightmaptexture = false;
11329                         for (;j < endsurface;j++)
11330                         {
11331                                 surface = rsurface.modelsurfaces + surfacelist[j];
11332                                 if (texture != surface->texture)
11333                                         break;
11334                                 texturesurfacelist[texturenumsurfaces++] = surface;
11335                         }
11336                 }
11337                 else
11338                 {
11339                         rsurface.lightmaptexture = surface->lightmaptexture;
11340                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11341                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11342                         for (;j < endsurface;j++)
11343                         {
11344                                 surface = rsurface.modelsurfaces + surfacelist[j];
11345                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11346                                         break;
11347                                 texturesurfacelist[texturenumsurfaces++] = surface;
11348                         }
11349                 }
11350                 // render the range of surfaces
11351                 if (ent == r_refdef.scene.worldentity)
11352                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11353                 else
11354                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11355         }
11356         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11357 }
11358
11359 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11360 {
11361         // transparent surfaces get pushed off into the transparent queue
11362         int surfacelistindex;
11363         const msurface_t *surface;
11364         vec3_t tempcenter, center;
11365         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11366         {
11367                 surface = texturesurfacelist[surfacelistindex];
11368                 if (r_transparent_sortsurfacesbynearest.integer)
11369                 {
11370                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11371                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11372                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11373                 }
11374                 else
11375                 {
11376                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11377                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11378                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11379                 }
11380                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11381                 if (rsurface.entity->transparent_offset) // transparent offset
11382                 {
11383                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11384                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11385                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11386                 }
11387                 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);
11388         }
11389 }
11390
11391 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11392 {
11393         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11394                 return;
11395         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11396                 return;
11397         RSurf_SetupDepthAndCulling();
11398         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11399         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11400         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11401         RSurf_DrawBatch();
11402 }
11403
11404 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11405 {
11406         CHECKGLERROR
11407         if (depthonly)
11408                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11409         else if (prepass)
11410         {
11411                 if (!rsurface.texture->currentnumlayers)
11412                         return;
11413                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11414                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11415                 else
11416                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11417         }
11418         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11419                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11420         else if (!rsurface.texture->currentnumlayers)
11421                 return;
11422         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11423         {
11424                 // in the deferred case, transparent surfaces were queued during prepass
11425                 if (!r_shadow_usingdeferredprepass)
11426                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11427         }
11428         else
11429         {
11430                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11431                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11432         }
11433         CHECKGLERROR
11434 }
11435
11436 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11437 {
11438         int i, j;
11439         texture_t *texture;
11440         R_FrameData_SetMark();
11441         // break the surface list down into batches by texture and use of lightmapping
11442         for (i = 0;i < numsurfaces;i = j)
11443         {
11444                 j = i + 1;
11445                 // texture is the base texture pointer, rsurface.texture is the
11446                 // current frame/skin the texture is directing us to use (for example
11447                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11448                 // use skin 1 instead)
11449                 texture = surfacelist[i]->texture;
11450                 rsurface.texture = R_GetCurrentTexture(texture);
11451                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11452                 {
11453                         // if this texture is not the kind we want, skip ahead to the next one
11454                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11455                                 ;
11456                         continue;
11457                 }
11458                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11459                 {
11460                         rsurface.lightmaptexture = NULL;
11461                         rsurface.deluxemaptexture = NULL;
11462                         rsurface.uselightmaptexture = false;
11463                         // simply scan ahead until we find a different texture or lightmap state
11464                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11465                                 ;
11466                 }
11467                 else
11468                 {
11469                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11470                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11471                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11472                         // simply scan ahead until we find a different texture or lightmap state
11473                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11474                                 ;
11475                 }
11476                 // render the range of surfaces
11477                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11478         }
11479         R_FrameData_ReturnToMark();
11480 }
11481
11482 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11483 {
11484         CHECKGLERROR
11485         if (depthonly)
11486                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11487         else if (prepass)
11488         {
11489                 if (!rsurface.texture->currentnumlayers)
11490                         return;
11491                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11492                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11493                 else
11494                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11495         }
11496         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11497                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11498         else if (!rsurface.texture->currentnumlayers)
11499                 return;
11500         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11501         {
11502                 // in the deferred case, transparent surfaces were queued during prepass
11503                 if (!r_shadow_usingdeferredprepass)
11504                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11505         }
11506         else
11507         {
11508                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11509                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11510         }
11511         CHECKGLERROR
11512 }
11513
11514 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11515 {
11516         int i, j;
11517         texture_t *texture;
11518         R_FrameData_SetMark();
11519         // break the surface list down into batches by texture and use of lightmapping
11520         for (i = 0;i < numsurfaces;i = j)
11521         {
11522                 j = i + 1;
11523                 // texture is the base texture pointer, rsurface.texture is the
11524                 // current frame/skin the texture is directing us to use (for example
11525                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11526                 // use skin 1 instead)
11527                 texture = surfacelist[i]->texture;
11528                 rsurface.texture = R_GetCurrentTexture(texture);
11529                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11530                 {
11531                         // if this texture is not the kind we want, skip ahead to the next one
11532                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11533                                 ;
11534                         continue;
11535                 }
11536                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11537                 {
11538                         rsurface.lightmaptexture = NULL;
11539                         rsurface.deluxemaptexture = NULL;
11540                         rsurface.uselightmaptexture = false;
11541                         // simply scan ahead until we find a different texture or lightmap state
11542                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11543                                 ;
11544                 }
11545                 else
11546                 {
11547                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11548                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11549                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11550                         // simply scan ahead until we find a different texture or lightmap state
11551                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11552                                 ;
11553                 }
11554                 // render the range of surfaces
11555                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11556         }
11557         R_FrameData_ReturnToMark();
11558 }
11559
11560 float locboxvertex3f[6*4*3] =
11561 {
11562         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11563         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11564         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11565         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11566         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11567         1,0,0, 0,0,0, 0,1,0, 1,1,0
11568 };
11569
11570 unsigned short locboxelements[6*2*3] =
11571 {
11572          0, 1, 2, 0, 2, 3,
11573          4, 5, 6, 4, 6, 7,
11574          8, 9,10, 8,10,11,
11575         12,13,14, 12,14,15,
11576         16,17,18, 16,18,19,
11577         20,21,22, 20,22,23
11578 };
11579
11580 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11581 {
11582         int i, j;
11583         cl_locnode_t *loc = (cl_locnode_t *)ent;
11584         vec3_t mins, size;
11585         float vertex3f[6*4*3];
11586         CHECKGLERROR
11587         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11588         GL_DepthMask(false);
11589         GL_DepthRange(0, 1);
11590         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11591         GL_DepthTest(true);
11592         GL_CullFace(GL_NONE);
11593         R_EntityMatrix(&identitymatrix);
11594
11595 //      R_Mesh_ResetTextureState();
11596
11597         i = surfacelist[0];
11598         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11599                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11600                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11601                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11602
11603         if (VectorCompare(loc->mins, loc->maxs))
11604         {
11605                 VectorSet(size, 2, 2, 2);
11606                 VectorMA(loc->mins, -0.5f, size, mins);
11607         }
11608         else
11609         {
11610                 VectorCopy(loc->mins, mins);
11611                 VectorSubtract(loc->maxs, loc->mins, size);
11612         }
11613
11614         for (i = 0;i < 6*4*3;)
11615                 for (j = 0;j < 3;j++, i++)
11616                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11617
11618         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11619         R_SetupShader_Generic_NoTexture(false, false);
11620         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11621 }
11622
11623 void R_DrawLocs(void)
11624 {
11625         int index;
11626         cl_locnode_t *loc, *nearestloc;
11627         vec3_t center;
11628         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11629         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11630         {
11631                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11632                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11633         }
11634 }
11635
11636 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11637 {
11638         if (decalsystem->decals)
11639                 Mem_Free(decalsystem->decals);
11640         memset(decalsystem, 0, sizeof(*decalsystem));
11641 }
11642
11643 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)
11644 {
11645         tridecal_t *decal;
11646         tridecal_t *decals;
11647         int i;
11648
11649         // expand or initialize the system
11650         if (decalsystem->maxdecals <= decalsystem->numdecals)
11651         {
11652                 decalsystem_t old = *decalsystem;
11653                 qboolean useshortelements;
11654                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11655                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11656                 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)));
11657                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11658                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11659                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11660                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11661                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11662                 if (decalsystem->numdecals)
11663                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11664                 if (old.decals)
11665                         Mem_Free(old.decals);
11666                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11667                         decalsystem->element3i[i] = i;
11668                 if (useshortelements)
11669                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11670                                 decalsystem->element3s[i] = i;
11671         }
11672
11673         // grab a decal and search for another free slot for the next one
11674         decals = decalsystem->decals;
11675         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11676         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11677                 ;
11678         decalsystem->freedecal = i;
11679         if (decalsystem->numdecals <= i)
11680                 decalsystem->numdecals = i + 1;
11681
11682         // initialize the decal
11683         decal->lived = 0;
11684         decal->triangleindex = triangleindex;
11685         decal->surfaceindex = surfaceindex;
11686         decal->decalsequence = decalsequence;
11687         decal->color4f[0][0] = c0[0];
11688         decal->color4f[0][1] = c0[1];
11689         decal->color4f[0][2] = c0[2];
11690         decal->color4f[0][3] = 1;
11691         decal->color4f[1][0] = c1[0];
11692         decal->color4f[1][1] = c1[1];
11693         decal->color4f[1][2] = c1[2];
11694         decal->color4f[1][3] = 1;
11695         decal->color4f[2][0] = c2[0];
11696         decal->color4f[2][1] = c2[1];
11697         decal->color4f[2][2] = c2[2];
11698         decal->color4f[2][3] = 1;
11699         decal->vertex3f[0][0] = v0[0];
11700         decal->vertex3f[0][1] = v0[1];
11701         decal->vertex3f[0][2] = v0[2];
11702         decal->vertex3f[1][0] = v1[0];
11703         decal->vertex3f[1][1] = v1[1];
11704         decal->vertex3f[1][2] = v1[2];
11705         decal->vertex3f[2][0] = v2[0];
11706         decal->vertex3f[2][1] = v2[1];
11707         decal->vertex3f[2][2] = v2[2];
11708         decal->texcoord2f[0][0] = t0[0];
11709         decal->texcoord2f[0][1] = t0[1];
11710         decal->texcoord2f[1][0] = t1[0];
11711         decal->texcoord2f[1][1] = t1[1];
11712         decal->texcoord2f[2][0] = t2[0];
11713         decal->texcoord2f[2][1] = t2[1];
11714         TriangleNormal(v0, v1, v2, decal->plane);
11715         VectorNormalize(decal->plane);
11716         decal->plane[3] = DotProduct(v0, decal->plane);
11717 }
11718
11719 extern cvar_t cl_decals_bias;
11720 extern cvar_t cl_decals_models;
11721 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11722 // baseparms, parms, temps
11723 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)
11724 {
11725         int cornerindex;
11726         int index;
11727         float v[9][3];
11728         const float *vertex3f;
11729         const float *normal3f;
11730         int numpoints;
11731         float points[2][9][3];
11732         float temp[3];
11733         float tc[9][2];
11734         float f;
11735         float c[9][4];
11736         const int *e;
11737
11738         e = rsurface.modelelement3i + 3*triangleindex;
11739
11740         vertex3f = rsurface.modelvertex3f;
11741         normal3f = rsurface.modelnormal3f;
11742
11743         if (normal3f)
11744         {
11745                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11746                 {
11747                         index = 3*e[cornerindex];
11748                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11749                 }
11750         }
11751         else
11752         {
11753                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11754                 {
11755                         index = 3*e[cornerindex];
11756                         VectorCopy(vertex3f + index, v[cornerindex]);
11757                 }
11758         }
11759
11760         // cull backfaces
11761         //TriangleNormal(v[0], v[1], v[2], normal);
11762         //if (DotProduct(normal, localnormal) < 0.0f)
11763         //      continue;
11764         // clip by each of the box planes formed from the projection matrix
11765         // if anything survives, we emit the decal
11766         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]);
11767         if (numpoints < 3)
11768                 return;
11769         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]);
11770         if (numpoints < 3)
11771                 return;
11772         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]);
11773         if (numpoints < 3)
11774                 return;
11775         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]);
11776         if (numpoints < 3)
11777                 return;
11778         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]);
11779         if (numpoints < 3)
11780                 return;
11781         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]);
11782         if (numpoints < 3)
11783                 return;
11784         // some part of the triangle survived, so we have to accept it...
11785         if (dynamic)
11786         {
11787                 // dynamic always uses the original triangle
11788                 numpoints = 3;
11789                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11790                 {
11791                         index = 3*e[cornerindex];
11792                         VectorCopy(vertex3f + index, v[cornerindex]);
11793                 }
11794         }
11795         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11796         {
11797                 // convert vertex positions to texcoords
11798                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11799                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11800                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11801                 // calculate distance fade from the projection origin
11802                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11803                 f = bound(0.0f, f, 1.0f);
11804                 c[cornerindex][0] = r * f;
11805                 c[cornerindex][1] = g * f;
11806                 c[cornerindex][2] = b * f;
11807                 c[cornerindex][3] = 1.0f;
11808                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11809         }
11810         if (dynamic)
11811                 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);
11812         else
11813                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11814                         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);
11815 }
11816 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)
11817 {
11818         matrix4x4_t projection;
11819         decalsystem_t *decalsystem;
11820         qboolean dynamic;
11821         dp_model_t *model;
11822         const msurface_t *surface;
11823         const msurface_t *surfaces;
11824         const int *surfacelist;
11825         const texture_t *texture;
11826         int numtriangles;
11827         int numsurfacelist;
11828         int surfacelistindex;
11829         int surfaceindex;
11830         int triangleindex;
11831         float localorigin[3];
11832         float localnormal[3];
11833         float localmins[3];
11834         float localmaxs[3];
11835         float localsize;
11836         //float normal[3];
11837         float planes[6][4];
11838         float angles[3];
11839         bih_t *bih;
11840         int bih_triangles_count;
11841         int bih_triangles[256];
11842         int bih_surfaces[256];
11843
11844         decalsystem = &ent->decalsystem;
11845         model = ent->model;
11846         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11847         {
11848                 R_DecalSystem_Reset(&ent->decalsystem);
11849                 return;
11850         }
11851
11852         if (!model->brush.data_leafs && !cl_decals_models.integer)
11853         {
11854                 if (decalsystem->model)
11855                         R_DecalSystem_Reset(decalsystem);
11856                 return;
11857         }
11858
11859         if (decalsystem->model != model)
11860                 R_DecalSystem_Reset(decalsystem);
11861         decalsystem->model = model;
11862
11863         RSurf_ActiveModelEntity(ent, true, false, false);
11864
11865         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11866         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11867         VectorNormalize(localnormal);
11868         localsize = worldsize*rsurface.inversematrixscale;
11869         localmins[0] = localorigin[0] - localsize;
11870         localmins[1] = localorigin[1] - localsize;
11871         localmins[2] = localorigin[2] - localsize;
11872         localmaxs[0] = localorigin[0] + localsize;
11873         localmaxs[1] = localorigin[1] + localsize;
11874         localmaxs[2] = localorigin[2] + localsize;
11875
11876         //VectorCopy(localnormal, planes[4]);
11877         //VectorVectors(planes[4], planes[2], planes[0]);
11878         AnglesFromVectors(angles, localnormal, NULL, false);
11879         AngleVectors(angles, planes[0], planes[2], planes[4]);
11880         VectorNegate(planes[0], planes[1]);
11881         VectorNegate(planes[2], planes[3]);
11882         VectorNegate(planes[4], planes[5]);
11883         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11884         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11885         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11886         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11887         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11888         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11889
11890 #if 1
11891 // works
11892 {
11893         matrix4x4_t forwardprojection;
11894         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11895         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11896 }
11897 #else
11898 // broken
11899 {
11900         float projectionvector[4][3];
11901         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11902         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11903         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11904         projectionvector[0][0] = planes[0][0] * ilocalsize;
11905         projectionvector[0][1] = planes[1][0] * ilocalsize;
11906         projectionvector[0][2] = planes[2][0] * ilocalsize;
11907         projectionvector[1][0] = planes[0][1] * ilocalsize;
11908         projectionvector[1][1] = planes[1][1] * ilocalsize;
11909         projectionvector[1][2] = planes[2][1] * ilocalsize;
11910         projectionvector[2][0] = planes[0][2] * ilocalsize;
11911         projectionvector[2][1] = planes[1][2] * ilocalsize;
11912         projectionvector[2][2] = planes[2][2] * ilocalsize;
11913         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11914         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11915         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11916         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11917 }
11918 #endif
11919
11920         dynamic = model->surfmesh.isanimated;
11921         numsurfacelist = model->nummodelsurfaces;
11922         surfacelist = model->sortedmodelsurfaces;
11923         surfaces = model->data_surfaces;
11924
11925         bih = NULL;
11926         bih_triangles_count = -1;
11927         if(!dynamic)
11928         {
11929                 if(model->render_bih.numleafs)
11930                         bih = &model->render_bih;
11931                 else if(model->collision_bih.numleafs)
11932                         bih = &model->collision_bih;
11933         }
11934         if(bih)
11935                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11936         if(bih_triangles_count == 0)
11937                 return;
11938         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11939                 return;
11940         if(bih_triangles_count > 0)
11941         {
11942                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11943                 {
11944                         surfaceindex = bih_surfaces[triangleindex];
11945                         surface = surfaces + surfaceindex;
11946                         texture = surface->texture;
11947                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11948                                 continue;
11949                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11950                                 continue;
11951                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11952                 }
11953         }
11954         else
11955         {
11956                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11957                 {
11958                         surfaceindex = surfacelist[surfacelistindex];
11959                         surface = surfaces + surfaceindex;
11960                         // check cull box first because it rejects more than any other check
11961                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11962                                 continue;
11963                         // skip transparent surfaces
11964                         texture = surface->texture;
11965                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11966                                 continue;
11967                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11968                                 continue;
11969                         numtriangles = surface->num_triangles;
11970                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11971                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11972                 }
11973         }
11974 }
11975
11976 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11977 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)
11978 {
11979         int renderentityindex;
11980         float worldmins[3];
11981         float worldmaxs[3];
11982         entity_render_t *ent;
11983
11984         if (!cl_decals_newsystem.integer)
11985                 return;
11986
11987         worldmins[0] = worldorigin[0] - worldsize;
11988         worldmins[1] = worldorigin[1] - worldsize;
11989         worldmins[2] = worldorigin[2] - worldsize;
11990         worldmaxs[0] = worldorigin[0] + worldsize;
11991         worldmaxs[1] = worldorigin[1] + worldsize;
11992         worldmaxs[2] = worldorigin[2] + worldsize;
11993
11994         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11995
11996         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11997         {
11998                 ent = r_refdef.scene.entities[renderentityindex];
11999                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12000                         continue;
12001
12002                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12003         }
12004 }
12005
12006 typedef struct r_decalsystem_splatqueue_s
12007 {
12008         vec3_t worldorigin;
12009         vec3_t worldnormal;
12010         float color[4];
12011         float tcrange[4];
12012         float worldsize;
12013         unsigned int decalsequence;
12014 }
12015 r_decalsystem_splatqueue_t;
12016
12017 int r_decalsystem_numqueued = 0;
12018 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12019
12020 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)
12021 {
12022         r_decalsystem_splatqueue_t *queue;
12023
12024         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12025                 return;
12026
12027         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12028         VectorCopy(worldorigin, queue->worldorigin);
12029         VectorCopy(worldnormal, queue->worldnormal);
12030         Vector4Set(queue->color, r, g, b, a);
12031         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12032         queue->worldsize = worldsize;
12033         queue->decalsequence = cl.decalsequence++;
12034 }
12035
12036 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12037 {
12038         int i;
12039         r_decalsystem_splatqueue_t *queue;
12040
12041         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12042                 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);
12043         r_decalsystem_numqueued = 0;
12044 }
12045
12046 extern cvar_t cl_decals_max;
12047 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12048 {
12049         int i;
12050         decalsystem_t *decalsystem = &ent->decalsystem;
12051         int numdecals;
12052         unsigned int killsequence;
12053         tridecal_t *decal;
12054         float frametime;
12055         float lifetime;
12056
12057         if (!decalsystem->numdecals)
12058                 return;
12059
12060         if (r_showsurfaces.integer)
12061                 return;
12062
12063         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12064         {
12065                 R_DecalSystem_Reset(decalsystem);
12066                 return;
12067         }
12068
12069         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12070         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12071
12072         if (decalsystem->lastupdatetime)
12073                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12074         else
12075                 frametime = 0;
12076         decalsystem->lastupdatetime = r_refdef.scene.time;
12077         numdecals = decalsystem->numdecals;
12078
12079         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12080         {
12081                 if (decal->color4f[0][3])
12082                 {
12083                         decal->lived += frametime;
12084                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12085                         {
12086                                 memset(decal, 0, sizeof(*decal));
12087                                 if (decalsystem->freedecal > i)
12088                                         decalsystem->freedecal = i;
12089                         }
12090                 }
12091         }
12092         decal = decalsystem->decals;
12093         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12094                 numdecals--;
12095
12096         // collapse the array by shuffling the tail decals into the gaps
12097         for (;;)
12098         {
12099                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12100                         decalsystem->freedecal++;
12101                 if (decalsystem->freedecal == numdecals)
12102                         break;
12103                 decal[decalsystem->freedecal] = decal[--numdecals];
12104         }
12105
12106         decalsystem->numdecals = numdecals;
12107
12108         if (numdecals <= 0)
12109         {
12110                 // if there are no decals left, reset decalsystem
12111                 R_DecalSystem_Reset(decalsystem);
12112         }
12113 }
12114
12115 extern skinframe_t *decalskinframe;
12116 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12117 {
12118         int i;
12119         decalsystem_t *decalsystem = &ent->decalsystem;
12120         int numdecals;
12121         tridecal_t *decal;
12122         float faderate;
12123         float alpha;
12124         float *v3f;
12125         float *c4f;
12126         float *t2f;
12127         const int *e;
12128         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12129         int numtris = 0;
12130
12131         numdecals = decalsystem->numdecals;
12132         if (!numdecals)
12133                 return;
12134
12135         if (r_showsurfaces.integer)
12136                 return;
12137
12138         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12139         {
12140                 R_DecalSystem_Reset(decalsystem);
12141                 return;
12142         }
12143
12144         // if the model is static it doesn't matter what value we give for
12145         // wantnormals and wanttangents, so this logic uses only rules applicable
12146         // to a model, knowing that they are meaningless otherwise
12147         if (ent == r_refdef.scene.worldentity)
12148                 RSurf_ActiveWorldEntity();
12149         else
12150                 RSurf_ActiveModelEntity(ent, false, false, false);
12151
12152         decalsystem->lastupdatetime = r_refdef.scene.time;
12153
12154         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12155
12156         // update vertex positions for animated models
12157         v3f = decalsystem->vertex3f;
12158         c4f = decalsystem->color4f;
12159         t2f = decalsystem->texcoord2f;
12160         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12161         {
12162                 if (!decal->color4f[0][3])
12163                         continue;
12164
12165                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12166                         continue;
12167
12168                 // skip backfaces
12169                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12170                         continue;
12171
12172                 // update color values for fading decals
12173                 if (decal->lived >= cl_decals_time.value)
12174                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12175                 else
12176                         alpha = 1.0f;
12177
12178                 c4f[ 0] = decal->color4f[0][0] * alpha;
12179                 c4f[ 1] = decal->color4f[0][1] * alpha;
12180                 c4f[ 2] = decal->color4f[0][2] * alpha;
12181                 c4f[ 3] = 1;
12182                 c4f[ 4] = decal->color4f[1][0] * alpha;
12183                 c4f[ 5] = decal->color4f[1][1] * alpha;
12184                 c4f[ 6] = decal->color4f[1][2] * alpha;
12185                 c4f[ 7] = 1;
12186                 c4f[ 8] = decal->color4f[2][0] * alpha;
12187                 c4f[ 9] = decal->color4f[2][1] * alpha;
12188                 c4f[10] = decal->color4f[2][2] * alpha;
12189                 c4f[11] = 1;
12190
12191                 t2f[0] = decal->texcoord2f[0][0];
12192                 t2f[1] = decal->texcoord2f[0][1];
12193                 t2f[2] = decal->texcoord2f[1][0];
12194                 t2f[3] = decal->texcoord2f[1][1];
12195                 t2f[4] = decal->texcoord2f[2][0];
12196                 t2f[5] = decal->texcoord2f[2][1];
12197
12198                 // update vertex positions for animated models
12199                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12200                 {
12201                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12202                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12203                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12204                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12205                 }
12206                 else
12207                 {
12208                         VectorCopy(decal->vertex3f[0], v3f);
12209                         VectorCopy(decal->vertex3f[1], v3f + 3);
12210                         VectorCopy(decal->vertex3f[2], v3f + 6);
12211                 }
12212
12213                 if (r_refdef.fogenabled)
12214                 {
12215                         alpha = RSurf_FogVertex(v3f);
12216                         VectorScale(c4f, alpha, c4f);
12217                         alpha = RSurf_FogVertex(v3f + 3);
12218                         VectorScale(c4f + 4, alpha, c4f + 4);
12219                         alpha = RSurf_FogVertex(v3f + 6);
12220                         VectorScale(c4f + 8, alpha, c4f + 8);
12221                 }
12222
12223                 v3f += 9;
12224                 c4f += 12;
12225                 t2f += 6;
12226                 numtris++;
12227         }
12228
12229         if (numtris > 0)
12230         {
12231                 r_refdef.stats[r_stat_drawndecals] += numtris;
12232
12233                 // now render the decals all at once
12234                 // (this assumes they all use one particle font texture!)
12235                 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);
12236 //              R_Mesh_ResetTextureState();
12237                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12238                 GL_DepthMask(false);
12239                 GL_DepthRange(0, 1);
12240                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12241                 GL_DepthTest(true);
12242                 GL_CullFace(GL_NONE);
12243                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12244                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12245                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12246         }
12247 }
12248
12249 static void R_DrawModelDecals(void)
12250 {
12251         int i, numdecals;
12252
12253         // fade faster when there are too many decals
12254         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12255         for (i = 0;i < r_refdef.scene.numentities;i++)
12256                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12257
12258         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12259         for (i = 0;i < r_refdef.scene.numentities;i++)
12260                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12261                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12262
12263         R_DecalSystem_ApplySplatEntitiesQueue();
12264
12265         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12266         for (i = 0;i < r_refdef.scene.numentities;i++)
12267                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12268
12269         r_refdef.stats[r_stat_totaldecals] += numdecals;
12270
12271         if (r_showsurfaces.integer)
12272                 return;
12273
12274         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12275
12276         for (i = 0;i < r_refdef.scene.numentities;i++)
12277         {
12278                 if (!r_refdef.viewcache.entityvisible[i])
12279                         continue;
12280                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12281                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12282         }
12283 }
12284
12285 extern cvar_t mod_collision_bih;
12286 static void R_DrawDebugModel(void)
12287 {
12288         entity_render_t *ent = rsurface.entity;
12289         int i, j, flagsmask;
12290         const msurface_t *surface;
12291         dp_model_t *model = ent->model;
12292
12293         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12294                 return;
12295
12296         if (r_showoverdraw.value > 0)
12297         {
12298                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12299                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12300                 R_SetupShader_Generic_NoTexture(false, false);
12301                 GL_DepthTest(false);
12302                 GL_DepthMask(false);
12303                 GL_DepthRange(0, 1);
12304                 GL_BlendFunc(GL_ONE, GL_ONE);
12305                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12306                 {
12307                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12308                                 continue;
12309                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12310                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12311                         {
12312                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12313                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12314                                 if (!rsurface.texture->currentlayers->depthmask)
12315                                         GL_Color(c, 0, 0, 1.0f);
12316                                 else if (ent == r_refdef.scene.worldentity)
12317                                         GL_Color(c, c, c, 1.0f);
12318                                 else
12319                                         GL_Color(0, c, 0, 1.0f);
12320                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12321                                 RSurf_DrawBatch();
12322                         }
12323                 }
12324                 rsurface.texture = NULL;
12325         }
12326
12327         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12328
12329 //      R_Mesh_ResetTextureState();
12330         R_SetupShader_Generic_NoTexture(false, false);
12331         GL_DepthRange(0, 1);
12332         GL_DepthTest(!r_showdisabledepthtest.integer);
12333         GL_DepthMask(false);
12334         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12335
12336         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12337         {
12338                 int triangleindex;
12339                 int bihleafindex;
12340                 qboolean cullbox = false;
12341                 const q3mbrush_t *brush;
12342                 const bih_t *bih = &model->collision_bih;
12343                 const bih_leaf_t *bihleaf;
12344                 float vertex3f[3][3];
12345                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12346                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12347                 {
12348                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12349                                 continue;
12350                         switch (bihleaf->type)
12351                         {
12352                         case BIH_BRUSH:
12353                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12354                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12355                                 {
12356                                         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);
12357                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12358                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12359                                 }
12360                                 break;
12361                         case BIH_COLLISIONTRIANGLE:
12362                                 triangleindex = bihleaf->itemindex;
12363                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12364                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12365                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12366                                 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);
12367                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12368                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12369                                 break;
12370                         case BIH_RENDERTRIANGLE:
12371                                 triangleindex = bihleaf->itemindex;
12372                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12373                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12374                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12375                                 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);
12376                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12377                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12378                                 break;
12379                         }
12380                 }
12381         }
12382
12383         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12384
12385 #ifndef USE_GLES2
12386         if (r_showtris.integer && qglPolygonMode)
12387         {
12388                 if (r_showdisabledepthtest.integer)
12389                 {
12390                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12391                         GL_DepthMask(false);
12392                 }
12393                 else
12394                 {
12395                         GL_BlendFunc(GL_ONE, GL_ZERO);
12396                         GL_DepthMask(true);
12397                 }
12398                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12399                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12400                 {
12401                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12402                                 continue;
12403                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12404                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12405                         {
12406                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12407                                 if (!rsurface.texture->currentlayers->depthmask)
12408                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12409                                 else if (ent == r_refdef.scene.worldentity)
12410                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12411                                 else
12412                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12413                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12414                                 RSurf_DrawBatch();
12415                         }
12416                 }
12417                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12418                 rsurface.texture = NULL;
12419         }
12420
12421         if (r_shownormals.value != 0 && qglBegin)
12422         {
12423                 int l, k;
12424                 vec3_t v;
12425                 if (r_showdisabledepthtest.integer)
12426                 {
12427                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12428                         GL_DepthMask(false);
12429                 }
12430                 else
12431                 {
12432                         GL_BlendFunc(GL_ONE, GL_ZERO);
12433                         GL_DepthMask(true);
12434                 }
12435                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12436                 {
12437                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12438                                 continue;
12439                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12440                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12441                         {
12442                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12443                                 qglBegin(GL_LINES);
12444                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12445                                 {
12446                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12447                                         {
12448                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12449                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12450                                                 qglVertex3f(v[0], v[1], v[2]);
12451                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12452                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12453                                                 qglVertex3f(v[0], v[1], v[2]);
12454                                         }
12455                                 }
12456                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12457                                 {
12458                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12459                                         {
12460                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12461                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12462                                                 qglVertex3f(v[0], v[1], v[2]);
12463                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12464                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12465                                                 qglVertex3f(v[0], v[1], v[2]);
12466                                         }
12467                                 }
12468                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12469                                 {
12470                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12471                                         {
12472                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12473                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12474                                                 qglVertex3f(v[0], v[1], v[2]);
12475                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12476                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12477                                                 qglVertex3f(v[0], v[1], v[2]);
12478                                         }
12479                                 }
12480                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12481                                 {
12482                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12483                                         {
12484                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12485                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12486                                                 qglVertex3f(v[0], v[1], v[2]);
12487                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12488                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12489                                                 qglVertex3f(v[0], v[1], v[2]);
12490                                         }
12491                                 }
12492                                 qglEnd();
12493                                 CHECKGLERROR
12494                         }
12495                 }
12496                 rsurface.texture = NULL;
12497         }
12498 #endif
12499 }
12500
12501 int r_maxsurfacelist = 0;
12502 const msurface_t **r_surfacelist = NULL;
12503 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12504 {
12505         int i, j, endj, flagsmask;
12506         dp_model_t *model = r_refdef.scene.worldmodel;
12507         msurface_t *surfaces;
12508         unsigned char *update;
12509         int numsurfacelist = 0;
12510         if (model == NULL)
12511                 return;
12512
12513         if (r_maxsurfacelist < model->num_surfaces)
12514         {
12515                 r_maxsurfacelist = model->num_surfaces;
12516                 if (r_surfacelist)
12517                         Mem_Free((msurface_t**)r_surfacelist);
12518                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12519         }
12520
12521         RSurf_ActiveWorldEntity();
12522
12523         surfaces = model->data_surfaces;
12524         update = model->brushq1.lightmapupdateflags;
12525
12526         // update light styles on this submodel
12527         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12528         {
12529                 model_brush_lightstyleinfo_t *style;
12530                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12531                 {
12532                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12533                         {
12534                                 int *list = style->surfacelist;
12535                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12536                                 for (j = 0;j < style->numsurfaces;j++)
12537                                         update[list[j]] = true;
12538                         }
12539                 }
12540         }
12541
12542         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12543
12544         if (debug)
12545         {
12546                 R_DrawDebugModel();
12547                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12548                 return;
12549         }
12550
12551         rsurface.lightmaptexture = NULL;
12552         rsurface.deluxemaptexture = NULL;
12553         rsurface.uselightmaptexture = false;
12554         rsurface.texture = NULL;
12555         rsurface.rtlight = NULL;
12556         numsurfacelist = 0;
12557         // add visible surfaces to draw list
12558         for (i = 0;i < model->nummodelsurfaces;i++)
12559         {
12560                 j = model->sortedmodelsurfaces[i];
12561                 if (r_refdef.viewcache.world_surfacevisible[j])
12562                         r_surfacelist[numsurfacelist++] = surfaces + j;
12563         }
12564         // update lightmaps if needed
12565         if (model->brushq1.firstrender)
12566         {
12567                 model->brushq1.firstrender = false;
12568                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12569                         if (update[j])
12570                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12571         }
12572         else if (update)
12573         {
12574                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12575                         if (r_refdef.viewcache.world_surfacevisible[j])
12576                                 if (update[j])
12577                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12578         }
12579         // don't do anything if there were no surfaces
12580         if (!numsurfacelist)
12581         {
12582                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12583                 return;
12584         }
12585         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12586
12587         // add to stats if desired
12588         if (r_speeds.integer && !skysurfaces && !depthonly)
12589         {
12590                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12591                 for (j = 0;j < numsurfacelist;j++)
12592                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12593         }
12594
12595         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12596 }
12597
12598 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12599 {
12600         int i, j, endj, flagsmask;
12601         dp_model_t *model = ent->model;
12602         msurface_t *surfaces;
12603         unsigned char *update;
12604         int numsurfacelist = 0;
12605         if (model == NULL)
12606                 return;
12607
12608         if (r_maxsurfacelist < model->num_surfaces)
12609         {
12610                 r_maxsurfacelist = model->num_surfaces;
12611                 if (r_surfacelist)
12612                         Mem_Free((msurface_t **)r_surfacelist);
12613                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12614         }
12615
12616         // if the model is static it doesn't matter what value we give for
12617         // wantnormals and wanttangents, so this logic uses only rules applicable
12618         // to a model, knowing that they are meaningless otherwise
12619         if (ent == r_refdef.scene.worldentity)
12620                 RSurf_ActiveWorldEntity();
12621         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12622                 RSurf_ActiveModelEntity(ent, false, false, false);
12623         else if (prepass)
12624                 RSurf_ActiveModelEntity(ent, true, true, true);
12625         else if (depthonly)
12626         {
12627                 switch (vid.renderpath)
12628                 {
12629                 case RENDERPATH_GL20:
12630                 case RENDERPATH_D3D9:
12631                 case RENDERPATH_D3D10:
12632                 case RENDERPATH_D3D11:
12633                 case RENDERPATH_SOFT:
12634                 case RENDERPATH_GLES2:
12635                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12636                         break;
12637                 case RENDERPATH_GL11:
12638                 case RENDERPATH_GL13:
12639                 case RENDERPATH_GLES1:
12640                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12641                         break;
12642                 }
12643         }
12644         else
12645         {
12646                 switch (vid.renderpath)
12647                 {
12648                 case RENDERPATH_GL20:
12649                 case RENDERPATH_D3D9:
12650                 case RENDERPATH_D3D10:
12651                 case RENDERPATH_D3D11:
12652                 case RENDERPATH_SOFT:
12653                 case RENDERPATH_GLES2:
12654                         RSurf_ActiveModelEntity(ent, true, true, false);
12655                         break;
12656                 case RENDERPATH_GL11:
12657                 case RENDERPATH_GL13:
12658                 case RENDERPATH_GLES1:
12659                         RSurf_ActiveModelEntity(ent, true, false, false);
12660                         break;
12661                 }
12662         }
12663
12664         surfaces = model->data_surfaces;
12665         update = model->brushq1.lightmapupdateflags;
12666
12667         // update light styles
12668         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12669         {
12670                 model_brush_lightstyleinfo_t *style;
12671                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12672                 {
12673                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12674                         {
12675                                 int *list = style->surfacelist;
12676                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12677                                 for (j = 0;j < style->numsurfaces;j++)
12678                                         update[list[j]] = true;
12679                         }
12680                 }
12681         }
12682
12683         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12684
12685         if (debug)
12686         {
12687                 R_DrawDebugModel();
12688                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12689                 return;
12690         }
12691
12692         rsurface.lightmaptexture = NULL;
12693         rsurface.deluxemaptexture = NULL;
12694         rsurface.uselightmaptexture = false;
12695         rsurface.texture = NULL;
12696         rsurface.rtlight = NULL;
12697         numsurfacelist = 0;
12698         // add visible surfaces to draw list
12699         for (i = 0;i < model->nummodelsurfaces;i++)
12700                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12701         // don't do anything if there were no surfaces
12702         if (!numsurfacelist)
12703         {
12704                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12705                 return;
12706         }
12707         // update lightmaps if needed
12708         if (update)
12709         {
12710                 int updated = 0;
12711                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12712                 {
12713                         if (update[j])
12714                         {
12715                                 updated++;
12716                                 R_BuildLightMap(ent, surfaces + j);
12717                         }
12718                 }
12719         }
12720
12721         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12722
12723         // add to stats if desired
12724         if (r_speeds.integer && !skysurfaces && !depthonly)
12725         {
12726                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12727                 for (j = 0;j < numsurfacelist;j++)
12728                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12729         }
12730
12731         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12732 }
12733
12734 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12735 {
12736         static texture_t texture;
12737         static msurface_t surface;
12738         const msurface_t *surfacelist = &surface;
12739
12740         // fake enough texture and surface state to render this geometry
12741
12742         texture.update_lastrenderframe = -1; // regenerate this texture
12743         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12744         texture.basealpha = 1.0f;
12745         texture.currentskinframe = skinframe;
12746         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12747         texture.offsetmapping = OFFSETMAPPING_OFF;
12748         texture.offsetscale = 1;
12749         texture.specularscalemod = 1;
12750         texture.specularpowermod = 1;
12751         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12752         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12753         // JUST GREP FOR "specularscalemod = 1".
12754
12755         surface.texture = &texture;
12756         surface.num_triangles = numtriangles;
12757         surface.num_firsttriangle = firsttriangle;
12758         surface.num_vertices = numvertices;
12759         surface.num_firstvertex = firstvertex;
12760
12761         // now render it
12762         rsurface.texture = R_GetCurrentTexture(surface.texture);
12763         rsurface.lightmaptexture = NULL;
12764         rsurface.deluxemaptexture = NULL;
12765         rsurface.uselightmaptexture = false;
12766         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12767 }
12768
12769 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)
12770 {
12771         static msurface_t surface;
12772         const msurface_t *surfacelist = &surface;
12773
12774         // fake enough texture and surface state to render this geometry
12775         surface.texture = texture;
12776         surface.num_triangles = numtriangles;
12777         surface.num_firsttriangle = firsttriangle;
12778         surface.num_vertices = numvertices;
12779         surface.num_firstvertex = firstvertex;
12780
12781         // now render it
12782         rsurface.texture = R_GetCurrentTexture(surface.texture);
12783         rsurface.lightmaptexture = NULL;
12784         rsurface.deluxemaptexture = NULL;
12785         rsurface.uselightmaptexture = false;
12786         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12787 }