]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix C++ compile error
[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_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
188 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"};
189 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
190 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
191 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
192 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"};
193 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"};
194 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)"};
195
196 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
197 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
198 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
199 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
200
201 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
202 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
203
204 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
205 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
206 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
207 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
208 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
209 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
210
211 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
212 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
213 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
214 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
215 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
218 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
219 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
220 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
221
222 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"};
223
224 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"};
225
226 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
227
228 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
229
230 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)"};
231 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)"};
232 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
234
235 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
236 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"};
237
238 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."};
239
240 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)"};
241 cvar_t r_bufferdatasize[R_BUFFERDATA_COUNT] =
242 {
243         {CVAR_SAVE, "r_bufferdatasize_vertex", "4", "vertex buffer size for one frame"},
244         {CVAR_SAVE, "r_bufferdatasize_index16", "1", "index buffer size for one frame (16bit indices)"},
245         {CVAR_SAVE, "r_bufferdatasize_index32", "1", "index buffer size for one frame (32bit indices)"},
246         {CVAR_SAVE, "r_bufferdatasize_uniform", "0.25", "uniform buffer size for one frame"},
247 };
248
249 extern cvar_t v_glslgamma;
250 extern cvar_t v_glslgamma_2d;
251
252 extern qboolean v_flipped_state;
253
254 r_framebufferstate_t r_fb;
255
256 /// shadow volume bsp struct with automatically growing nodes buffer
257 svbsp_t r_svbsp;
258
259 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
260
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
274
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
277 {
278         char basename[64];
279         rtexture_t *texture;
280 }
281 cubemapinfo_t;
282
283 int r_texture_numcubemaps;
284 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
285
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
289
290 typedef struct r_qwskincache_s
291 {
292         char name[MAX_QPATH];
293         skinframe_t *skinframe;
294 }
295 r_qwskincache_t;
296
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
299
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
304 {
305         0, 0, 0,
306         1, 0, 0,
307         1, 1, 0,
308         0, 1, 0
309 };
310 const float r_d3dscreenvertex3f[12] =
311 {
312         0, 1, 0,
313         1, 1, 0,
314         1, 0, 0,
315         0, 0, 0
316 };
317
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
319 {
320         int i;
321         for (i = 0;i < verts;i++)
322         {
323                 out[0] = in[0] * r;
324                 out[1] = in[1] * g;
325                 out[2] = in[2] * b;
326                 out[3] = in[3];
327                 in += 4;
328                 out += 4;
329         }
330 }
331
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = r;
338                 out[1] = g;
339                 out[2] = b;
340                 out[3] = a;
341                 out += 4;
342         }
343 }
344
345 // FIXME: move this to client?
346 void FOG_clear(void)
347 {
348         if (gamemode == GAME_NEHAHRA)
349         {
350                 Cvar_Set("gl_fogenable", "0");
351                 Cvar_Set("gl_fogdensity", "0.2");
352                 Cvar_Set("gl_fogred", "0.3");
353                 Cvar_Set("gl_foggreen", "0.3");
354                 Cvar_Set("gl_fogblue", "0.3");
355         }
356         r_refdef.fog_density = 0;
357         r_refdef.fog_red = 0;
358         r_refdef.fog_green = 0;
359         r_refdef.fog_blue = 0;
360         r_refdef.fog_alpha = 1;
361         r_refdef.fog_start = 0;
362         r_refdef.fog_end = 16384;
363         r_refdef.fog_height = 1<<30;
364         r_refdef.fog_fadedepth = 128;
365         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
366 }
367
368 static void R_BuildBlankTextures(void)
369 {
370         unsigned char data[4];
371         data[2] = 128; // normal X
372         data[1] = 128; // normal Y
373         data[0] = 255; // normal Z
374         data[3] = 255; // height
375         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 255;
377         data[1] = 255;
378         data[2] = 255;
379         data[3] = 255;
380         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 128;
382         data[1] = 128;
383         data[2] = 128;
384         data[3] = 255;
385         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 0;
387         data[1] = 0;
388         data[2] = 0;
389         data[3] = 255;
390         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildNoTexture(void)
394 {
395         int x, y;
396         unsigned char pix[16][16][4];
397         // this makes a light grey/dark grey checkerboard texture
398         for (y = 0;y < 16;y++)
399         {
400                 for (x = 0;x < 16;x++)
401                 {
402                         if ((y < 8) ^ (x < 8))
403                         {
404                                 pix[y][x][0] = 128;
405                                 pix[y][x][1] = 128;
406                                 pix[y][x][2] = 128;
407                                 pix[y][x][3] = 255;
408                         }
409                         else
410                         {
411                                 pix[y][x][0] = 64;
412                                 pix[y][x][1] = 64;
413                                 pix[y][x][2] = 64;
414                                 pix[y][x][3] = 255;
415                         }
416                 }
417         }
418         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
419 }
420
421 static void R_BuildWhiteCube(void)
422 {
423         unsigned char data[6*1*1*4];
424         memset(data, 255, sizeof(data));
425         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
426 }
427
428 static void R_BuildNormalizationCube(void)
429 {
430         int x, y, side;
431         vec3_t v;
432         vec_t s, t, intensity;
433 #define NORMSIZE 64
434         unsigned char *data;
435         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436         for (side = 0;side < 6;side++)
437         {
438                 for (y = 0;y < NORMSIZE;y++)
439                 {
440                         for (x = 0;x < NORMSIZE;x++)
441                         {
442                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 switch(side)
445                                 {
446                                 default:
447                                 case 0:
448                                         v[0] = 1;
449                                         v[1] = -t;
450                                         v[2] = -s;
451                                         break;
452                                 case 1:
453                                         v[0] = -1;
454                                         v[1] = -t;
455                                         v[2] = s;
456                                         break;
457                                 case 2:
458                                         v[0] = s;
459                                         v[1] = 1;
460                                         v[2] = t;
461                                         break;
462                                 case 3:
463                                         v[0] = s;
464                                         v[1] = -1;
465                                         v[2] = -t;
466                                         break;
467                                 case 4:
468                                         v[0] = s;
469                                         v[1] = -t;
470                                         v[2] = 1;
471                                         break;
472                                 case 5:
473                                         v[0] = -s;
474                                         v[1] = -t;
475                                         v[2] = -1;
476                                         break;
477                                 }
478                                 intensity = 127.0f / sqrt(DotProduct(v, v));
479                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482                                 data[((side*64+y)*64+x)*4+3] = 255;
483                         }
484                 }
485         }
486         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
487         Mem_Free(data);
488 }
489
490 static void R_BuildFogTexture(void)
491 {
492         int x, b;
493 #define FOGWIDTH 256
494         unsigned char data1[FOGWIDTH][4];
495         //unsigned char data2[FOGWIDTH][4];
496         double d, r, alpha;
497
498         r_refdef.fogmasktable_start = r_refdef.fog_start;
499         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500         r_refdef.fogmasktable_range = r_refdef.fogrange;
501         r_refdef.fogmasktable_density = r_refdef.fog_density;
502
503         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505         {
506                 d = (x * r - r_refdef.fogmasktable_start);
507                 if(developer_extra.integer)
508                         Con_DPrintf("%f ", d);
509                 d = max(0, d);
510                 if (r_fog_exp2.integer)
511                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512                 else
513                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514                 if(developer_extra.integer)
515                         Con_DPrintf(" : %f ", alpha);
516                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517                 if(developer_extra.integer)
518                         Con_DPrintf(" = %f\n", alpha);
519                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
520         }
521
522         for (x = 0;x < FOGWIDTH;x++)
523         {
524                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
525                 data1[x][0] = b;
526                 data1[x][1] = b;
527                 data1[x][2] = b;
528                 data1[x][3] = 255;
529                 //data2[x][0] = 255 - b;
530                 //data2[x][1] = 255 - b;
531                 //data2[x][2] = 255 - b;
532                 //data2[x][3] = 255;
533         }
534         if (r_texture_fogattenuation)
535         {
536                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538         }
539         else
540         {
541                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
543         }
544 }
545
546 static void R_BuildFogHeightTexture(void)
547 {
548         unsigned char *inpixels;
549         int size;
550         int x;
551         int y;
552         int j;
553         float c[4];
554         float f;
555         inpixels = NULL;
556         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557         if (r_refdef.fogheighttexturename[0])
558                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
559         if (!inpixels)
560         {
561                 r_refdef.fog_height_tablesize = 0;
562                 if (r_texture_fogheighttexture)
563                         R_FreeTexture(r_texture_fogheighttexture);
564                 r_texture_fogheighttexture = NULL;
565                 if (r_refdef.fog_height_table2d)
566                         Mem_Free(r_refdef.fog_height_table2d);
567                 r_refdef.fog_height_table2d = NULL;
568                 if (r_refdef.fog_height_table1d)
569                         Mem_Free(r_refdef.fog_height_table1d);
570                 r_refdef.fog_height_table1d = NULL;
571                 return;
572         }
573         size = image_width;
574         r_refdef.fog_height_tablesize = size;
575         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578         Mem_Free(inpixels);
579         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
580         // average fog color table accounting for every fog layer between a point
581         // and the camera.  (Note: attenuation is handled separately!)
582         for (y = 0;y < size;y++)
583         {
584                 for (x = 0;x < size;x++)
585                 {
586                         Vector4Clear(c);
587                         f = 0;
588                         if (x < y)
589                         {
590                                 for (j = x;j <= y;j++)
591                                 {
592                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
593                                         f++;
594                                 }
595                         }
596                         else
597                         {
598                                 for (j = x;j >= y;j--)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         f = 1.0f / f;
605                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
609                 }
610         }
611         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
612 }
613
614 //=======================================================================================================================================================
615
616 static const char *builtinshaderstrings[] =
617 {
618 #include "shader_glsl.h"
619 0
620 };
621
622 const char *builtinhlslshaderstrings[] =
623 {
624 #include "shader_hlsl.h"
625 0
626 };
627
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
630
631 //=======================================================================================================================================================
632
633 typedef struct shaderpermutationinfo_s
634 {
635         const char *pretext;
636         const char *name;
637 }
638 shaderpermutationinfo_t;
639
640 typedef struct shadermodeinfo_s
641 {
642         const char *filename;
643         const char *pretext;
644         const char *name;
645 }
646 shadermodeinfo_t;
647
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {
651         {"#define USEDIFFUSE\n", " diffuse"},
652         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653         {"#define USEVIEWTINT\n", " viewtint"},
654         {"#define USECOLORMAPPING\n", " colormapping"},
655         {"#define USESATURATION\n", " saturation"},
656         {"#define USEFOGINSIDE\n", " foginside"},
657         {"#define USEFOGOUTSIDE\n", " fogoutside"},
658         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660         {"#define USEGAMMARAMPS\n", " gammaramps"},
661         {"#define USECUBEFILTER\n", " cubefilter"},
662         {"#define USEGLOW\n", " glow"},
663         {"#define USEBLOOM\n", " bloom"},
664         {"#define USESPECULAR\n", " specular"},
665         {"#define USEPOSTPROCESSING\n", " postprocessing"},
666         {"#define USEREFLECTION\n", " reflection"},
667         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
671         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673         {"#define USEALPHAKILL\n", " alphakill"},
674         {"#define USEREFLECTCUBE\n", " reflectcube"},
675         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676         {"#define USEBOUNCEGRID\n", " bouncegrid"},
677         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
678         {"#define USETRIPPY\n", " trippy"},
679         {"#define USEDEPTHRGB\n", " depthrgb"},
680         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
681         {"#define USESKELETAL\n", " skeletal"}
682 };
683
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
686 {
687         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
697         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
698         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
699         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
700         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
701         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
702         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
707 {
708         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
725 };
726
727 struct r_glsl_permutation_s;
728 typedef struct r_glsl_permutation_s
729 {
730         /// hash lookup data
731         struct r_glsl_permutation_s *hashnext;
732         unsigned int mode;
733         unsigned int permutation;
734
735         /// indicates if we have tried compiling this permutation already
736         qboolean compiled;
737         /// 0 if compilation failed
738         int program;
739         // texture units assigned to each detected uniform
740         int tex_Texture_First;
741         int tex_Texture_Second;
742         int tex_Texture_GammaRamps;
743         int tex_Texture_Normal;
744         int tex_Texture_Color;
745         int tex_Texture_Gloss;
746         int tex_Texture_Glow;
747         int tex_Texture_SecondaryNormal;
748         int tex_Texture_SecondaryColor;
749         int tex_Texture_SecondaryGloss;
750         int tex_Texture_SecondaryGlow;
751         int tex_Texture_Pants;
752         int tex_Texture_Shirt;
753         int tex_Texture_FogHeightTexture;
754         int tex_Texture_FogMask;
755         int tex_Texture_Lightmap;
756         int tex_Texture_Deluxemap;
757         int tex_Texture_Attenuation;
758         int tex_Texture_Cube;
759         int tex_Texture_Refraction;
760         int tex_Texture_Reflection;
761         int tex_Texture_ShadowMap2D;
762         int tex_Texture_CubeProjection;
763         int tex_Texture_ScreenNormalMap;
764         int tex_Texture_ScreenDiffuse;
765         int tex_Texture_ScreenSpecular;
766         int tex_Texture_ReflectMask;
767         int tex_Texture_ReflectCube;
768         int tex_Texture_BounceGrid;
769         /// locations of detected uniforms in program object, or -1 if not found
770         int loc_Texture_First;
771         int loc_Texture_Second;
772         int loc_Texture_GammaRamps;
773         int loc_Texture_Normal;
774         int loc_Texture_Color;
775         int loc_Texture_Gloss;
776         int loc_Texture_Glow;
777         int loc_Texture_SecondaryNormal;
778         int loc_Texture_SecondaryColor;
779         int loc_Texture_SecondaryGloss;
780         int loc_Texture_SecondaryGlow;
781         int loc_Texture_Pants;
782         int loc_Texture_Shirt;
783         int loc_Texture_FogHeightTexture;
784         int loc_Texture_FogMask;
785         int loc_Texture_Lightmap;
786         int loc_Texture_Deluxemap;
787         int loc_Texture_Attenuation;
788         int loc_Texture_Cube;
789         int loc_Texture_Refraction;
790         int loc_Texture_Reflection;
791         int loc_Texture_ShadowMap2D;
792         int loc_Texture_CubeProjection;
793         int loc_Texture_ScreenNormalMap;
794         int loc_Texture_ScreenDiffuse;
795         int loc_Texture_ScreenSpecular;
796         int loc_Texture_ReflectMask;
797         int loc_Texture_ReflectCube;
798         int loc_Texture_BounceGrid;
799         int loc_Alpha;
800         int loc_BloomBlur_Parameters;
801         int loc_ClientTime;
802         int loc_Color_Ambient;
803         int loc_Color_Diffuse;
804         int loc_Color_Specular;
805         int loc_Color_Glow;
806         int loc_Color_Pants;
807         int loc_Color_Shirt;
808         int loc_DeferredColor_Ambient;
809         int loc_DeferredColor_Diffuse;
810         int loc_DeferredColor_Specular;
811         int loc_DeferredMod_Diffuse;
812         int loc_DeferredMod_Specular;
813         int loc_DistortScaleRefractReflect;
814         int loc_EyePosition;
815         int loc_FogColor;
816         int loc_FogHeightFade;
817         int loc_FogPlane;
818         int loc_FogPlaneViewDist;
819         int loc_FogRangeRecip;
820         int loc_LightColor;
821         int loc_LightDir;
822         int loc_LightPosition;
823         int loc_OffsetMapping_ScaleSteps;
824         int loc_OffsetMapping_LodDistance;
825         int loc_OffsetMapping_Bias;
826         int loc_PixelSize;
827         int loc_ReflectColor;
828         int loc_ReflectFactor;
829         int loc_ReflectOffset;
830         int loc_RefractColor;
831         int loc_Saturation;
832         int loc_ScreenCenterRefractReflect;
833         int loc_ScreenScaleRefractReflect;
834         int loc_ScreenToDepth;
835         int loc_ShadowMap_Parameters;
836         int loc_ShadowMap_TextureScale;
837         int loc_SpecularPower;
838         int loc_Skeletal_Transform12;
839         int loc_UserVec1;
840         int loc_UserVec2;
841         int loc_UserVec3;
842         int loc_UserVec4;
843         int loc_ViewTintColor;
844         int loc_ViewToLight;
845         int loc_ModelToLight;
846         int loc_TexMatrix;
847         int loc_BackgroundTexMatrix;
848         int loc_ModelViewProjectionMatrix;
849         int loc_ModelViewMatrix;
850         int loc_PixelToScreenTexCoord;
851         int loc_ModelToReflectCube;
852         int loc_ShadowMapMatrix;
853         int loc_BloomColorSubtract;
854         int loc_NormalmapScrollBlend;
855         int loc_BounceGridMatrix;
856         int loc_BounceGridIntensity;
857         /// uniform block bindings
858         int ubibind_Skeletal_Transform12_UniformBlock;
859         /// uniform block indices
860         int ubiloc_Skeletal_Transform12_UniformBlock;
861 }
862 r_glsl_permutation_t;
863
864 #define SHADERPERMUTATION_HASHSIZE 256
865
866
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
869 enum
870 {
871         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
877         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
879         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
880         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
881         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
882         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
883         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
884 };
885 #define SHADERSTATICPARMS_COUNT 13
886
887 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
888 static int shaderstaticparms_count = 0;
889
890 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
891 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
892
893 extern qboolean r_shadow_shadowmapsampler;
894 extern int r_shadow_shadowmappcf;
895 qboolean R_CompileShader_CheckStaticParms(void)
896 {
897         static int r_compileshader_staticparms_save[1];
898         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
899         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
900
901         // detect all
902         if (r_glsl_saturation_redcompensate.integer)
903                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
904         if (r_glsl_vertextextureblend_usebothalphas.integer)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
906         if (r_shadow_glossexact.integer)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
908         if (r_glsl_postprocess.integer)
909         {
910                 if (r_glsl_postprocess_uservec1_enable.integer)
911                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
912                 if (r_glsl_postprocess_uservec2_enable.integer)
913                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
914                 if (r_glsl_postprocess_uservec3_enable.integer)
915                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
916                 if (r_glsl_postprocess_uservec4_enable.integer)
917                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
918         }
919         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
920                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
921
922         if (r_shadow_shadowmapsampler)
923                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
924         if (r_shadow_shadowmappcf > 1)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
926         else if (r_shadow_shadowmappcf)
927                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
928         if (r_celshading.integer)
929                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
930         if (r_celoutlines.integer)
931                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
932
933         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
934 }
935
936 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
937         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
938                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
939         else \
940                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
941 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
942 {
943         shaderstaticparms_count = 0;
944
945         // emit all
946         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
947         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
948         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
949         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
950         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
951         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
952         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
953         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
954         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
955         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
956         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
957         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
958         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
959 }
960
961 /// information about each possible shader permutation
962 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
963 /// currently selected permutation
964 r_glsl_permutation_t *r_glsl_permutation;
965 /// storage for permutations linked in the hash table
966 memexpandablearray_t r_glsl_permutationarray;
967
968 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
969 {
970         //unsigned int hashdepth = 0;
971         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
972         r_glsl_permutation_t *p;
973         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
974         {
975                 if (p->mode == mode && p->permutation == permutation)
976                 {
977                         //if (hashdepth > 10)
978                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
979                         return p;
980                 }
981                 //hashdepth++;
982         }
983         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
984         p->mode = mode;
985         p->permutation = permutation;
986         p->hashnext = r_glsl_permutationhash[mode][hashindex];
987         r_glsl_permutationhash[mode][hashindex] = p;
988         //if (hashdepth > 10)
989         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
990         return p;
991 }
992
993 static char *R_ShaderStrCat(const char **strings)
994 {
995         char *string, *s;
996         const char **p = strings;
997         const char *t;
998         size_t len = 0;
999         for (p = strings;(t = *p);p++)
1000                 len += strlen(t);
1001         len++;
1002         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1003         len = 0;
1004         for (p = strings;(t = *p);p++)
1005         {
1006                 len = strlen(t);
1007                 memcpy(s, t, len);
1008                 s += len;
1009         }
1010         *s = 0;
1011         return string;
1012 }
1013
1014 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1015 {
1016         char *shaderstring;
1017         if (!filename || !filename[0])
1018                 return NULL;
1019         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1020         if (!strcmp(filename, "glsl/default.glsl"))
1021         {
1022                 if (builtinonly)
1023                         return R_ShaderStrCat(builtinshaderstrings);
1024                 if (!glslshaderstring)
1025                 {
1026                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1027                         if (glslshaderstring)
1028                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1029                         else
1030                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1031                 }
1032                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1033                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1034                 return shaderstring;
1035         }
1036         if (!strcmp(filename, "hlsl/default.hlsl"))
1037         {
1038                 if (builtinonly)
1039                         return R_ShaderStrCat(builtinhlslshaderstrings);
1040                 if (!hlslshaderstring)
1041                 {
1042                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1043                         if (hlslshaderstring)
1044                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1045                         else
1046                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1047                 }
1048                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1049                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1050                 return shaderstring;
1051         }
1052         // we don't have builtin strings for any other files
1053         if (builtinonly)
1054                 return NULL;
1055         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1056         if (shaderstring)
1057         {
1058                 if (printfromdisknotice)
1059                         Con_DPrintf("from disk %s... ", filename);
1060                 return shaderstring;
1061         }
1062         return shaderstring;
1063 }
1064
1065 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1066 {
1067         int i;
1068         int ubibind;
1069         int sampler;
1070         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1071         char *sourcestring;
1072         char permutationname[256];
1073         int vertstrings_count = 0;
1074         int geomstrings_count = 0;
1075         int fragstrings_count = 0;
1076         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1077         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1078         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1079
1080         if (p->compiled)
1081                 return;
1082         p->compiled = true;
1083         p->program = 0;
1084
1085         permutationname[0] = 0;
1086         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1087
1088         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1089
1090         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1091         if(vid.support.glshaderversion >= 140)
1092         {
1093                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1094                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1095                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1096                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1097                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1098                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1099         }
1100         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1101         else if(vid.support.glshaderversion >= 130)
1102         {
1103                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1104                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1105                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1106                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1107                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1108                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1109         }
1110
1111         // the first pretext is which type of shader to compile as
1112         // (later these will all be bound together as a program object)
1113         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1114         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1115         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1116
1117         // the second pretext is the mode (for example a light source)
1118         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1119         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1120         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1121         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1122
1123         // now add all the permutation pretexts
1124         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1125         {
1126                 if (permutation & (1<<i))
1127                 {
1128                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1129                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1130                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1131                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1132                 }
1133                 else
1134                 {
1135                         // keep line numbers correct
1136                         vertstrings_list[vertstrings_count++] = "\n";
1137                         geomstrings_list[geomstrings_count++] = "\n";
1138                         fragstrings_list[fragstrings_count++] = "\n";
1139                 }
1140         }
1141
1142         // add static parms
1143         R_CompileShader_AddStaticParms(mode, permutation);
1144         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1145         vertstrings_count += shaderstaticparms_count;
1146         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1147         geomstrings_count += shaderstaticparms_count;
1148         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1149         fragstrings_count += shaderstaticparms_count;
1150
1151         // now append the shader text itself
1152         vertstrings_list[vertstrings_count++] = sourcestring;
1153         geomstrings_list[geomstrings_count++] = sourcestring;
1154         fragstrings_list[fragstrings_count++] = sourcestring;
1155
1156         // compile the shader program
1157         if (vertstrings_count + geomstrings_count + fragstrings_count)
1158                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1159         if (p->program)
1160         {
1161                 CHECKGLERROR
1162                 qglUseProgram(p->program);CHECKGLERROR
1163                 // look up all the uniform variable names we care about, so we don't
1164                 // have to look them up every time we set them
1165
1166                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1167                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1168                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1169                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1170                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1171                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1172                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1173                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1174                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1175                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1176                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1177                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1178                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1179                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1180                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1181                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1182                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1183                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1184                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1185                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1186                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1187                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1188                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1189                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1190                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1191                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1192                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1193                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1194                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1195                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1196                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1197                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1198                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1199                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1200                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1201                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1202                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1203                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1204                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1205                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1206                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1207                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1208                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1209                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1210                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1211                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1212                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1213                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1214                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1215                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1216                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1217                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1218                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1219                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1220                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1221                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1222                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1223                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1224                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1225                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1226                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1227                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1228                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1229                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1230                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1231                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1232                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1233                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1234                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1235                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1236                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1237                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1238                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1239                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1240                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1241                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1242                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1243                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1244                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1245                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1246                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1247                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1248                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1249                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1250                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1251                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1252                 // initialize the samplers to refer to the texture units we use
1253                 p->tex_Texture_First = -1;
1254                 p->tex_Texture_Second = -1;
1255                 p->tex_Texture_GammaRamps = -1;
1256                 p->tex_Texture_Normal = -1;
1257                 p->tex_Texture_Color = -1;
1258                 p->tex_Texture_Gloss = -1;
1259                 p->tex_Texture_Glow = -1;
1260                 p->tex_Texture_SecondaryNormal = -1;
1261                 p->tex_Texture_SecondaryColor = -1;
1262                 p->tex_Texture_SecondaryGloss = -1;
1263                 p->tex_Texture_SecondaryGlow = -1;
1264                 p->tex_Texture_Pants = -1;
1265                 p->tex_Texture_Shirt = -1;
1266                 p->tex_Texture_FogHeightTexture = -1;
1267                 p->tex_Texture_FogMask = -1;
1268                 p->tex_Texture_Lightmap = -1;
1269                 p->tex_Texture_Deluxemap = -1;
1270                 p->tex_Texture_Attenuation = -1;
1271                 p->tex_Texture_Cube = -1;
1272                 p->tex_Texture_Refraction = -1;
1273                 p->tex_Texture_Reflection = -1;
1274                 p->tex_Texture_ShadowMap2D = -1;
1275                 p->tex_Texture_CubeProjection = -1;
1276                 p->tex_Texture_ScreenNormalMap = -1;
1277                 p->tex_Texture_ScreenDiffuse = -1;
1278                 p->tex_Texture_ScreenSpecular = -1;
1279                 p->tex_Texture_ReflectMask = -1;
1280                 p->tex_Texture_ReflectCube = -1;
1281                 p->tex_Texture_BounceGrid = -1;
1282                 // bind the texture samplers in use
1283                 sampler = 0;
1284                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1285                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1286                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1287                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1288                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1289                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1290                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1291                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1292                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1293                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1294                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1295                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1296                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1297                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1298                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1299                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1300                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1301                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1302                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1303                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1304                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1305                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1306                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1307                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1308                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1309                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1310                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1311                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1312                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1313                 // get the uniform block indices so we can bind them
1314                 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1315                 // clear the uniform block bindings
1316                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1317                 // bind the uniform blocks in use
1318                 ubibind = 0;
1319                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1320                 // we're done compiling and setting up the shader, at least until it is used
1321                 CHECKGLERROR
1322                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1323         }
1324         else
1325                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1326
1327         // free the strings
1328         if (sourcestring)
1329                 Mem_Free(sourcestring);
1330 }
1331
1332 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1333 {
1334         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1335         if (r_glsl_permutation != perm)
1336         {
1337                 r_glsl_permutation = perm;
1338                 if (!r_glsl_permutation->program)
1339                 {
1340                         if (!r_glsl_permutation->compiled)
1341                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1342                         if (!r_glsl_permutation->program)
1343                         {
1344                                 // remove features until we find a valid permutation
1345                                 int i;
1346                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1347                                 {
1348                                         // reduce i more quickly whenever it would not remove any bits
1349                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1350                                         if (!(permutation & j))
1351                                                 continue;
1352                                         permutation -= j;
1353                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1354                                         if (!r_glsl_permutation->compiled)
1355                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1356                                         if (r_glsl_permutation->program)
1357                                                 break;
1358                                 }
1359                                 if (i >= SHADERPERMUTATION_COUNT)
1360                                 {
1361                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1362                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1363                                         qglUseProgram(0);CHECKGLERROR
1364                                         return; // no bit left to clear, entire mode is broken
1365                                 }
1366                         }
1367                 }
1368                 CHECKGLERROR
1369                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1370         }
1371         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1372         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1373         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1374 }
1375
1376 #ifdef SUPPORTD3D
1377
1378 #ifdef SUPPORTD3D
1379 #include <d3d9.h>
1380 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1381 extern D3DCAPS9 vid_d3d9caps;
1382 #endif
1383
1384 struct r_hlsl_permutation_s;
1385 typedef struct r_hlsl_permutation_s
1386 {
1387         /// hash lookup data
1388         struct r_hlsl_permutation_s *hashnext;
1389         unsigned int mode;
1390         unsigned int permutation;
1391
1392         /// indicates if we have tried compiling this permutation already
1393         qboolean compiled;
1394         /// NULL if compilation failed
1395         IDirect3DVertexShader9 *vertexshader;
1396         IDirect3DPixelShader9 *pixelshader;
1397 }
1398 r_hlsl_permutation_t;
1399
1400 typedef enum D3DVSREGISTER_e
1401 {
1402         D3DVSREGISTER_TexMatrix = 0, // float4x4
1403         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1404         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1405         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1406         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1407         D3DVSREGISTER_ModelToLight = 20, // float4x4
1408         D3DVSREGISTER_EyePosition = 24,
1409         D3DVSREGISTER_FogPlane = 25,
1410         D3DVSREGISTER_LightDir = 26,
1411         D3DVSREGISTER_LightPosition = 27,
1412 }
1413 D3DVSREGISTER_t;
1414
1415 typedef enum D3DPSREGISTER_e
1416 {
1417         D3DPSREGISTER_Alpha = 0,
1418         D3DPSREGISTER_BloomBlur_Parameters = 1,
1419         D3DPSREGISTER_ClientTime = 2,
1420         D3DPSREGISTER_Color_Ambient = 3,
1421         D3DPSREGISTER_Color_Diffuse = 4,
1422         D3DPSREGISTER_Color_Specular = 5,
1423         D3DPSREGISTER_Color_Glow = 6,
1424         D3DPSREGISTER_Color_Pants = 7,
1425         D3DPSREGISTER_Color_Shirt = 8,
1426         D3DPSREGISTER_DeferredColor_Ambient = 9,
1427         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1428         D3DPSREGISTER_DeferredColor_Specular = 11,
1429         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1430         D3DPSREGISTER_DeferredMod_Specular = 13,
1431         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1432         D3DPSREGISTER_EyePosition = 15, // unused
1433         D3DPSREGISTER_FogColor = 16,
1434         D3DPSREGISTER_FogHeightFade = 17,
1435         D3DPSREGISTER_FogPlane = 18,
1436         D3DPSREGISTER_FogPlaneViewDist = 19,
1437         D3DPSREGISTER_FogRangeRecip = 20,
1438         D3DPSREGISTER_LightColor = 21,
1439         D3DPSREGISTER_LightDir = 22, // unused
1440         D3DPSREGISTER_LightPosition = 23,
1441         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1442         D3DPSREGISTER_PixelSize = 25,
1443         D3DPSREGISTER_ReflectColor = 26,
1444         D3DPSREGISTER_ReflectFactor = 27,
1445         D3DPSREGISTER_ReflectOffset = 28,
1446         D3DPSREGISTER_RefractColor = 29,
1447         D3DPSREGISTER_Saturation = 30,
1448         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1449         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1450         D3DPSREGISTER_ScreenToDepth = 33,
1451         D3DPSREGISTER_ShadowMap_Parameters = 34,
1452         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1453         D3DPSREGISTER_SpecularPower = 36,
1454         D3DPSREGISTER_UserVec1 = 37,
1455         D3DPSREGISTER_UserVec2 = 38,
1456         D3DPSREGISTER_UserVec3 = 39,
1457         D3DPSREGISTER_UserVec4 = 40,
1458         D3DPSREGISTER_ViewTintColor = 41,
1459         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1460         D3DPSREGISTER_BloomColorSubtract = 43,
1461         D3DPSREGISTER_ViewToLight = 44, // float4x4
1462         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1463         D3DPSREGISTER_NormalmapScrollBlend = 52,
1464         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1465         D3DPSREGISTER_OffsetMapping_Bias = 54,
1466         // next at 54
1467 }
1468 D3DPSREGISTER_t;
1469
1470 /// information about each possible shader permutation
1471 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1472 /// currently selected permutation
1473 r_hlsl_permutation_t *r_hlsl_permutation;
1474 /// storage for permutations linked in the hash table
1475 memexpandablearray_t r_hlsl_permutationarray;
1476
1477 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1478 {
1479         //unsigned int hashdepth = 0;
1480         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1481         r_hlsl_permutation_t *p;
1482         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1483         {
1484                 if (p->mode == mode && p->permutation == permutation)
1485                 {
1486                         //if (hashdepth > 10)
1487                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1488                         return p;
1489                 }
1490                 //hashdepth++;
1491         }
1492         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1493         p->mode = mode;
1494         p->permutation = permutation;
1495         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1496         r_hlsl_permutationhash[mode][hashindex] = p;
1497         //if (hashdepth > 10)
1498         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1499         return p;
1500 }
1501
1502 #include <d3dx9.h>
1503 //#include <d3dx9shader.h>
1504 //#include <d3dx9mesh.h>
1505
1506 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1507 {
1508         DWORD *vsbin = NULL;
1509         DWORD *psbin = NULL;
1510         fs_offset_t vsbinsize;
1511         fs_offset_t psbinsize;
1512 //      IDirect3DVertexShader9 *vs = NULL;
1513 //      IDirect3DPixelShader9 *ps = NULL;
1514         ID3DXBuffer *vslog = NULL;
1515         ID3DXBuffer *vsbuffer = NULL;
1516         ID3DXConstantTable *vsconstanttable = NULL;
1517         ID3DXBuffer *pslog = NULL;
1518         ID3DXBuffer *psbuffer = NULL;
1519         ID3DXConstantTable *psconstanttable = NULL;
1520         int vsresult = 0;
1521         int psresult = 0;
1522         char temp[MAX_INPUTLINE];
1523         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1524         char vabuf[1024];
1525         qboolean debugshader = gl_paranoid.integer != 0;
1526         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1527         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1528         if (!debugshader)
1529         {
1530                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1531                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1532         }
1533         if ((!vsbin && vertstring) || (!psbin && fragstring))
1534         {
1535                 const char* dllnames_d3dx9 [] =
1536                 {
1537                         "d3dx9_43.dll",
1538                         "d3dx9_42.dll",
1539                         "d3dx9_41.dll",
1540                         "d3dx9_40.dll",
1541                         "d3dx9_39.dll",
1542                         "d3dx9_38.dll",
1543                         "d3dx9_37.dll",
1544                         "d3dx9_36.dll",
1545                         "d3dx9_35.dll",
1546                         "d3dx9_34.dll",
1547                         "d3dx9_33.dll",
1548                         "d3dx9_32.dll",
1549                         "d3dx9_31.dll",
1550                         "d3dx9_30.dll",
1551                         "d3dx9_29.dll",
1552                         "d3dx9_28.dll",
1553                         "d3dx9_27.dll",
1554                         "d3dx9_26.dll",
1555                         "d3dx9_25.dll",
1556                         "d3dx9_24.dll",
1557                         NULL
1558                 };
1559                 dllhandle_t d3dx9_dll = NULL;
1560                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1561                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1562                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1563                 dllfunction_t d3dx9_dllfuncs[] =
1564                 {
1565                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1566                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1567                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1568                         {NULL, NULL}
1569                 };
1570                 // 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...
1571 #ifndef ID3DXBuffer_GetBufferPointer
1572 #if !defined(__cplusplus) || defined(CINTERFACE)
1573 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1574 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1575 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1576 #else
1577 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1578 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1579 #define ID3DXBuffer_Release(p)            (p)->Release()
1580 #endif
1581 #endif
1582                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1583                 {
1584                         DWORD shaderflags = 0;
1585                         if (debugshader)
1586                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1587                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1588                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1589                         if (vertstring && vertstring[0])
1590                         {
1591                                 if (debugshader)
1592                                 {
1593                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1594                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1595                                 }
1596                                 else
1597                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1598                                 if (vsbuffer)
1599                                 {
1600                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1601                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1602                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1603                                         ID3DXBuffer_Release(vsbuffer);
1604                                 }
1605                                 if (vslog)
1606                                 {
1607                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1608                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1609                                         ID3DXBuffer_Release(vslog);
1610                                 }
1611                         }
1612                         if (fragstring && fragstring[0])
1613                         {
1614                                 if (debugshader)
1615                                 {
1616                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1617                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1618                                 }
1619                                 else
1620                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1621                                 if (psbuffer)
1622                                 {
1623                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1624                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1625                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1626                                         ID3DXBuffer_Release(psbuffer);
1627                                 }
1628                                 if (pslog)
1629                                 {
1630                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1631                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1632                                         ID3DXBuffer_Release(pslog);
1633                                 }
1634                         }
1635                         Sys_UnloadLibrary(&d3dx9_dll);
1636                 }
1637                 else
1638                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1639         }
1640         if (vsbin && psbin)
1641         {
1642                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1643                 if (FAILED(vsresult))
1644                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1645                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1646                 if (FAILED(psresult))
1647                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1648         }
1649         // free the shader data
1650         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1651         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1652 }
1653
1654 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1655 {
1656         int i;
1657         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1658         int vertstring_length = 0;
1659         int geomstring_length = 0;
1660         int fragstring_length = 0;
1661         char *t;
1662         char *sourcestring;
1663         char *vertstring, *geomstring, *fragstring;
1664         char permutationname[256];
1665         char cachename[256];
1666         int vertstrings_count = 0;
1667         int geomstrings_count = 0;
1668         int fragstrings_count = 0;
1669         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1670         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1671         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1672
1673         if (p->compiled)
1674                 return;
1675         p->compiled = true;
1676         p->vertexshader = NULL;
1677         p->pixelshader = NULL;
1678
1679         permutationname[0] = 0;
1680         cachename[0] = 0;
1681         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1682
1683         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1684         strlcat(cachename, "hlsl/", sizeof(cachename));
1685
1686         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1687         vertstrings_count = 0;
1688         geomstrings_count = 0;
1689         fragstrings_count = 0;
1690         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1691         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1692         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1693
1694         // the first pretext is which type of shader to compile as
1695         // (later these will all be bound together as a program object)
1696         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1697         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1698         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1699
1700         // the second pretext is the mode (for example a light source)
1701         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1702         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1703         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1704         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1705         strlcat(cachename, modeinfo->name, sizeof(cachename));
1706
1707         // now add all the permutation pretexts
1708         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1709         {
1710                 if (permutation & (1<<i))
1711                 {
1712                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1713                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1714                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1715                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1716                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1717                 }
1718                 else
1719                 {
1720                         // keep line numbers correct
1721                         vertstrings_list[vertstrings_count++] = "\n";
1722                         geomstrings_list[geomstrings_count++] = "\n";
1723                         fragstrings_list[fragstrings_count++] = "\n";
1724                 }
1725         }
1726
1727         // add static parms
1728         R_CompileShader_AddStaticParms(mode, permutation);
1729         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1730         vertstrings_count += shaderstaticparms_count;
1731         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1732         geomstrings_count += shaderstaticparms_count;
1733         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1734         fragstrings_count += shaderstaticparms_count;
1735
1736         // replace spaces in the cachename with _ characters
1737         for (i = 0;cachename[i];i++)
1738                 if (cachename[i] == ' ')
1739                         cachename[i] = '_';
1740
1741         // now append the shader text itself
1742         vertstrings_list[vertstrings_count++] = sourcestring;
1743         geomstrings_list[geomstrings_count++] = sourcestring;
1744         fragstrings_list[fragstrings_count++] = sourcestring;
1745
1746         vertstring_length = 0;
1747         for (i = 0;i < vertstrings_count;i++)
1748                 vertstring_length += strlen(vertstrings_list[i]);
1749         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1750         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1751                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1752
1753         geomstring_length = 0;
1754         for (i = 0;i < geomstrings_count;i++)
1755                 geomstring_length += strlen(geomstrings_list[i]);
1756         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1757         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1758                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1759
1760         fragstring_length = 0;
1761         for (i = 0;i < fragstrings_count;i++)
1762                 fragstring_length += strlen(fragstrings_list[i]);
1763         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1764         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1765                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1766
1767         // try to load the cached shader, or generate one
1768         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1769
1770         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1771                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1772         else
1773                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1774
1775         // free the strings
1776         if (vertstring)
1777                 Mem_Free(vertstring);
1778         if (geomstring)
1779                 Mem_Free(geomstring);
1780         if (fragstring)
1781                 Mem_Free(fragstring);
1782         if (sourcestring)
1783                 Mem_Free(sourcestring);
1784 }
1785
1786 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1787 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1788 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);}
1789 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);}
1790 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);}
1791 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);}
1792
1793 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1794 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1795 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);}
1796 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);}
1797 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);}
1798 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);}
1799
1800 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1801 {
1802         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1803         if (r_hlsl_permutation != perm)
1804         {
1805                 r_hlsl_permutation = perm;
1806                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1807                 {
1808                         if (!r_hlsl_permutation->compiled)
1809                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1810                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1811                         {
1812                                 // remove features until we find a valid permutation
1813                                 int i;
1814                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1815                                 {
1816                                         // reduce i more quickly whenever it would not remove any bits
1817                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1818                                         if (!(permutation & j))
1819                                                 continue;
1820                                         permutation -= j;
1821                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1822                                         if (!r_hlsl_permutation->compiled)
1823                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1824                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1825                                                 break;
1826                                 }
1827                                 if (i >= SHADERPERMUTATION_COUNT)
1828                                 {
1829                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1830                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1831                                         return; // no bit left to clear, entire mode is broken
1832                                 }
1833                         }
1834                 }
1835                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1836                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1837         }
1838         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1839         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1840         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1841 }
1842 #endif
1843
1844 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1845 {
1846         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1847         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1848         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1849         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1850 }
1851
1852 void R_GLSL_Restart_f(void)
1853 {
1854         unsigned int i, limit;
1855         if (glslshaderstring)
1856                 Mem_Free(glslshaderstring);
1857         glslshaderstring = NULL;
1858         if (hlslshaderstring)
1859                 Mem_Free(hlslshaderstring);
1860         hlslshaderstring = NULL;
1861         switch(vid.renderpath)
1862         {
1863         case RENDERPATH_D3D9:
1864 #ifdef SUPPORTD3D
1865                 {
1866                         r_hlsl_permutation_t *p;
1867                         r_hlsl_permutation = NULL;
1868                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1869                         for (i = 0;i < limit;i++)
1870                         {
1871                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1872                                 {
1873                                         if (p->vertexshader)
1874                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1875                                         if (p->pixelshader)
1876                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1877                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1878                                 }
1879                         }
1880                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1881                 }
1882 #endif
1883                 break;
1884         case RENDERPATH_D3D10:
1885                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1886                 break;
1887         case RENDERPATH_D3D11:
1888                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1889                 break;
1890         case RENDERPATH_GL20:
1891         case RENDERPATH_GLES2:
1892                 {
1893                         r_glsl_permutation_t *p;
1894                         r_glsl_permutation = NULL;
1895                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1896                         for (i = 0;i < limit;i++)
1897                         {
1898                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1899                                 {
1900                                         GL_Backend_FreeProgram(p->program);
1901                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1902                                 }
1903                         }
1904                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1905                 }
1906                 break;
1907         case RENDERPATH_GL11:
1908         case RENDERPATH_GL13:
1909         case RENDERPATH_GLES1:
1910                 break;
1911         case RENDERPATH_SOFT:
1912                 break;
1913         }
1914 }
1915
1916 static void R_GLSL_DumpShader_f(void)
1917 {
1918         int i, language, mode, dupe;
1919         char *text;
1920         shadermodeinfo_t *modeinfo;
1921         qfile_t *file;
1922
1923         for (language = 0;language < 2;language++)
1924         {
1925                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1926                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1927                 {
1928                         // don't dump the same file multiple times (most or all shaders come from the same file)
1929                         for (dupe = mode - 1;dupe >= 0;dupe--)
1930                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1931                                         break;
1932                         if (dupe >= 0)
1933                                 continue;
1934                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1935                         if (!text)
1936                                 continue;
1937                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1938                         if (file)
1939                         {
1940                                 FS_Print(file, "/* The engine may define the following macros:\n");
1941                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1942                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1943                                         FS_Print(file, modeinfo[i].pretext);
1944                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1945                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1946                                 FS_Print(file, "*/\n");
1947                                 FS_Print(file, text);
1948                                 FS_Close(file);
1949                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1950                         }
1951                         else
1952                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1953                         Mem_Free(text);
1954                 }
1955         }
1956 }
1957
1958 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1959 {
1960         unsigned int permutation = 0;
1961         if (r_trippy.integer && !notrippy)
1962                 permutation |= SHADERPERMUTATION_TRIPPY;
1963         permutation |= SHADERPERMUTATION_VIEWTINT;
1964         if (first)
1965                 permutation |= SHADERPERMUTATION_DIFFUSE;
1966         if (second)
1967                 permutation |= SHADERPERMUTATION_SPECULAR;
1968         if (texturemode == GL_MODULATE)
1969                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1970         else if (texturemode == GL_ADD)
1971                 permutation |= SHADERPERMUTATION_GLOW;
1972         else if (texturemode == GL_DECAL)
1973                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1974         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1975                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1976         if (suppresstexalpha)
1977                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1978         if (!second)
1979                 texturemode = GL_MODULATE;
1980         if (vid.allowalphatocoverage)
1981                 GL_AlphaToCoverage(false);
1982         switch (vid.renderpath)
1983         {
1984         case RENDERPATH_D3D9:
1985 #ifdef SUPPORTD3D
1986                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1987                 R_Mesh_TexBind(GL20TU_FIRST , first );
1988                 R_Mesh_TexBind(GL20TU_SECOND, second);
1989                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1990                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1991 #endif
1992                 break;
1993         case RENDERPATH_D3D10:
1994                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1995                 break;
1996         case RENDERPATH_D3D11:
1997                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1998                 break;
1999         case RENDERPATH_GL20:
2000         case RENDERPATH_GLES2:
2001                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2002                 if (r_glsl_permutation->tex_Texture_First >= 0)
2003                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2004                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2005                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2006                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2007                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2008                 break;
2009         case RENDERPATH_GL13:
2010         case RENDERPATH_GLES1:
2011                 R_Mesh_TexBind(0, first );
2012                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2013                 R_Mesh_TexMatrix(0, NULL);
2014                 R_Mesh_TexBind(1, second);
2015                 if (second)
2016                 {
2017                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2018                         R_Mesh_TexMatrix(1, NULL);
2019                 }
2020                 break;
2021         case RENDERPATH_GL11:
2022                 R_Mesh_TexBind(0, first );
2023                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2024                 R_Mesh_TexMatrix(0, NULL);
2025                 break;
2026         case RENDERPATH_SOFT:
2027                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2028                 R_Mesh_TexBind(GL20TU_FIRST , first );
2029                 R_Mesh_TexBind(GL20TU_SECOND, second);
2030                 break;
2031         }
2032 }
2033
2034 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2035 {
2036         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2037 }
2038
2039 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2040 {
2041         unsigned int permutation = 0;
2042         if (r_trippy.integer && !notrippy)
2043                 permutation |= SHADERPERMUTATION_TRIPPY;
2044         if (depthrgb)
2045                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2046         if (skeletal)
2047                 permutation |= SHADERPERMUTATION_SKELETAL;
2048
2049         if (vid.allowalphatocoverage)
2050                 GL_AlphaToCoverage(false);
2051         switch (vid.renderpath)
2052         {
2053         case RENDERPATH_D3D9:
2054 #ifdef SUPPORTD3D
2055                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2056 #endif
2057                 break;
2058         case RENDERPATH_D3D10:
2059                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2060                 break;
2061         case RENDERPATH_D3D11:
2062                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2063                 break;
2064         case RENDERPATH_GL20:
2065         case RENDERPATH_GLES2:
2066                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2067                 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);
2068                 break;
2069         case RENDERPATH_GL13:
2070         case RENDERPATH_GLES1:
2071                 R_Mesh_TexBind(0, 0);
2072                 R_Mesh_TexBind(1, 0);
2073                 break;
2074         case RENDERPATH_GL11:
2075                 R_Mesh_TexBind(0, 0);
2076                 break;
2077         case RENDERPATH_SOFT:
2078                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2079                 break;
2080         }
2081 }
2082
2083 extern qboolean r_shadow_usingdeferredprepass;
2084 extern rtexture_t *r_shadow_attenuationgradienttexture;
2085 extern rtexture_t *r_shadow_attenuation2dtexture;
2086 extern rtexture_t *r_shadow_attenuation3dtexture;
2087 extern qboolean r_shadow_usingshadowmap2d;
2088 extern qboolean r_shadow_usingshadowmaportho;
2089 extern float r_shadow_shadowmap_texturescale[2];
2090 extern float r_shadow_shadowmap_parameters[4];
2091 extern qboolean r_shadow_shadowmapvsdct;
2092 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2093 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2094 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2095 extern matrix4x4_t r_shadow_shadowmapmatrix;
2096 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2097 extern int r_shadow_prepass_width;
2098 extern int r_shadow_prepass_height;
2099 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2100 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2101 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2102 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2103
2104 #define BLENDFUNC_ALLOWS_COLORMOD      1
2105 #define BLENDFUNC_ALLOWS_FOG           2
2106 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2107 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2108 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2109 static int R_BlendFuncFlags(int src, int dst)
2110 {
2111         int r = 0;
2112
2113         // a blendfunc allows colormod if:
2114         // a) it can never keep the destination pixel invariant, or
2115         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2116         // this is to prevent unintended side effects from colormod
2117
2118         // a blendfunc allows fog if:
2119         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2120         // this is to prevent unintended side effects from fog
2121
2122         // these checks are the output of fogeval.pl
2123
2124         r |= BLENDFUNC_ALLOWS_COLORMOD;
2125         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2126         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2127         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2128         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2129         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2130         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2131         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2132         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2133         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2134         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2135         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2136         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2137         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2138         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2139         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2140         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2141         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2142         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2143         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2144         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2145         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2146
2147         return r;
2148 }
2149
2150 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)
2151 {
2152         // select a permutation of the lighting shader appropriate to this
2153         // combination of texture, entity, light source, and fogging, only use the
2154         // minimum features necessary to avoid wasting rendering time in the
2155         // fragment shader on features that are not being used
2156         unsigned int permutation = 0;
2157         unsigned int mode = 0;
2158         int blendfuncflags;
2159         static float dummy_colormod[3] = {1, 1, 1};
2160         float *colormod = rsurface.colormod;
2161         float m16f[16];
2162         matrix4x4_t tempmatrix;
2163         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2164         if (r_trippy.integer && !notrippy)
2165                 permutation |= SHADERPERMUTATION_TRIPPY;
2166         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2167                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2168         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2169                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2170         if (rsurfacepass == RSURFPASS_BACKGROUND)
2171         {
2172                 // distorted background
2173                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2174                 {
2175                         mode = SHADERMODE_WATER;
2176                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2177                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2178                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2179                         {
2180                                 // this is the right thing to do for wateralpha
2181                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2182                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2183                         }
2184                         else
2185                         {
2186                                 // this is the right thing to do for entity alpha
2187                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2188                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2189                         }
2190                 }
2191                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2192                 {
2193                         mode = SHADERMODE_REFRACTION;
2194                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2195                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2196                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2197                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2198                 }
2199                 else
2200                 {
2201                         mode = SHADERMODE_GENERIC;
2202                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2203                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2204                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2205                 }
2206                 if (vid.allowalphatocoverage)
2207                         GL_AlphaToCoverage(false);
2208         }
2209         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2210         {
2211                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2212                 {
2213                         switch(rsurface.texture->offsetmapping)
2214                         {
2215                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2216                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2217                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2218                         case OFFSETMAPPING_OFF: break;
2219                         }
2220                 }
2221                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2222                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2223                 // normalmap (deferred prepass), may use alpha test on diffuse
2224                 mode = SHADERMODE_DEFERREDGEOMETRY;
2225                 GL_BlendFunc(GL_ONE, GL_ZERO);
2226                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2227                 if (vid.allowalphatocoverage)
2228                         GL_AlphaToCoverage(false);
2229         }
2230         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2231         {
2232                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2233                 {
2234                         switch(rsurface.texture->offsetmapping)
2235                         {
2236                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2237                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2238                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2239                         case OFFSETMAPPING_OFF: break;
2240                         }
2241                 }
2242                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2243                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2244                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2245                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2246                 // light source
2247                 mode = SHADERMODE_LIGHTSOURCE;
2248                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2249                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2250                 if (diffusescale > 0)
2251                         permutation |= SHADERPERMUTATION_DIFFUSE;
2252                 if (specularscale > 0)
2253                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2254                 if (r_refdef.fogenabled)
2255                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2256                 if (rsurface.texture->colormapping)
2257                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2258                 if (r_shadow_usingshadowmap2d)
2259                 {
2260                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2261                         if(r_shadow_shadowmapvsdct)
2262                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2263
2264                         if (r_shadow_shadowmap2ddepthbuffer)
2265                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2266                 }
2267                 if (rsurface.texture->reflectmasktexture)
2268                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2269                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2270                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2271                 if (vid.allowalphatocoverage)
2272                         GL_AlphaToCoverage(false);
2273         }
2274         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2275         {
2276                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2277                 {
2278                         switch(rsurface.texture->offsetmapping)
2279                         {
2280                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2281                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2282                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2283                         case OFFSETMAPPING_OFF: break;
2284                         }
2285                 }
2286                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2287                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2288                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2289                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2290                 // unshaded geometry (fullbright or ambient model lighting)
2291                 mode = SHADERMODE_FLATCOLOR;
2292                 ambientscale = diffusescale = specularscale = 0;
2293                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2294                         permutation |= SHADERPERMUTATION_GLOW;
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_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2300                 {
2301                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2302                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2303
2304                         if (r_shadow_shadowmap2ddepthbuffer)
2305                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2306                 }
2307                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2308                         permutation |= SHADERPERMUTATION_REFLECTION;
2309                 if (rsurface.texture->reflectmasktexture)
2310                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2311                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2312                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2313                 // when using alphatocoverage, we don't need alphakill
2314                 if (vid.allowalphatocoverage)
2315                 {
2316                         if (r_transparent_alphatocoverage.integer)
2317                         {
2318                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2319                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2320                         }
2321                         else
2322                                 GL_AlphaToCoverage(false);
2323                 }
2324         }
2325         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2326         {
2327                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2328                 {
2329                         switch(rsurface.texture->offsetmapping)
2330                         {
2331                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2332                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2333                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2334                         case OFFSETMAPPING_OFF: break;
2335                         }
2336                 }
2337                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2338                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2339                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2340                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2341                 // directional model lighting
2342                 mode = SHADERMODE_LIGHTDIRECTION;
2343                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2344                         permutation |= SHADERPERMUTATION_GLOW;
2345                 permutation |= SHADERPERMUTATION_DIFFUSE;
2346                 if (specularscale > 0)
2347                         permutation |= SHADERPERMUTATION_SPECULAR;
2348                 if (r_refdef.fogenabled)
2349                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2350                 if (rsurface.texture->colormapping)
2351                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2352                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2353                 {
2354                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2355                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2356
2357                         if (r_shadow_shadowmap2ddepthbuffer)
2358                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2359                 }
2360                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2361                         permutation |= SHADERPERMUTATION_REFLECTION;
2362                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2363                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2364                 if (rsurface.texture->reflectmasktexture)
2365                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2366                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2367                 {
2368                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2369                         if (r_shadow_bouncegriddirectional)
2370                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2371                 }
2372                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2373                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2374                 // when using alphatocoverage, we don't need alphakill
2375                 if (vid.allowalphatocoverage)
2376                 {
2377                         if (r_transparent_alphatocoverage.integer)
2378                         {
2379                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2380                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2381                         }
2382                         else
2383                                 GL_AlphaToCoverage(false);
2384                 }
2385         }
2386         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2387         {
2388                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2389                 {
2390                         switch(rsurface.texture->offsetmapping)
2391                         {
2392                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2393                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2394                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2395                         case OFFSETMAPPING_OFF: break;
2396                         }
2397                 }
2398                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2399                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2400                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2401                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2402                 // ambient model lighting
2403                 mode = SHADERMODE_LIGHTDIRECTION;
2404                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2405                         permutation |= SHADERPERMUTATION_GLOW;
2406                 if (r_refdef.fogenabled)
2407                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2408                 if (rsurface.texture->colormapping)
2409                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2410                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2411                 {
2412                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2413                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2414
2415                         if (r_shadow_shadowmap2ddepthbuffer)
2416                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2417                 }
2418                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2419                         permutation |= SHADERPERMUTATION_REFLECTION;
2420                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2421                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2422                 if (rsurface.texture->reflectmasktexture)
2423                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2424                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2425                 {
2426                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2427                         if (r_shadow_bouncegriddirectional)
2428                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2429                 }
2430                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2431                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2432                 // when using alphatocoverage, we don't need alphakill
2433                 if (vid.allowalphatocoverage)
2434                 {
2435                         if (r_transparent_alphatocoverage.integer)
2436                         {
2437                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2438                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2439                         }
2440                         else
2441                                 GL_AlphaToCoverage(false);
2442                 }
2443         }
2444         else
2445         {
2446                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2447                 {
2448                         switch(rsurface.texture->offsetmapping)
2449                         {
2450                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2451                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2452                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2453                         case OFFSETMAPPING_OFF: break;
2454                         }
2455                 }
2456                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2457                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2458                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2459                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2460                 // lightmapped wall
2461                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2462                         permutation |= SHADERPERMUTATION_GLOW;
2463                 if (r_refdef.fogenabled)
2464                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2465                 if (rsurface.texture->colormapping)
2466                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2467                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2468                 {
2469                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2470                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2471
2472                         if (r_shadow_shadowmap2ddepthbuffer)
2473                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2474                 }
2475                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2476                         permutation |= SHADERPERMUTATION_REFLECTION;
2477                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2478                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2479                 if (rsurface.texture->reflectmasktexture)
2480                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2481                 if (FAKELIGHT_ENABLED)
2482                 {
2483                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2484                         mode = SHADERMODE_FAKELIGHT;
2485                         permutation |= SHADERPERMUTATION_DIFFUSE;
2486                         if (specularscale > 0)
2487                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2488                 }
2489                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2490                 {
2491                         // deluxemapping (light direction texture)
2492                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2493                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2494                         else
2495                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2496                         permutation |= SHADERPERMUTATION_DIFFUSE;
2497                         if (specularscale > 0)
2498                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2499                 }
2500                 else if (r_glsl_deluxemapping.integer >= 2)
2501                 {
2502                         // fake deluxemapping (uniform light direction in tangentspace)
2503                         if (rsurface.uselightmaptexture)
2504                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2505                         else
2506                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2507                         permutation |= SHADERPERMUTATION_DIFFUSE;
2508                         if (specularscale > 0)
2509                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2510                 }
2511                 else if (rsurface.uselightmaptexture)
2512                 {
2513                         // ordinary lightmapping (q1bsp, q3bsp)
2514                         mode = SHADERMODE_LIGHTMAP;
2515                 }
2516                 else
2517                 {
2518                         // ordinary vertex coloring (q3bsp)
2519                         mode = SHADERMODE_VERTEXCOLOR;
2520                 }
2521                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2522                 {
2523                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2524                         if (r_shadow_bouncegriddirectional)
2525                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2526                 }
2527                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2528                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2529                 // when using alphatocoverage, we don't need alphakill
2530                 if (vid.allowalphatocoverage)
2531                 {
2532                         if (r_transparent_alphatocoverage.integer)
2533                         {
2534                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2535                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2536                         }
2537                         else
2538                                 GL_AlphaToCoverage(false);
2539                 }
2540         }
2541         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2542                 colormod = dummy_colormod;
2543         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2544                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2545         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2546                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2547         switch(vid.renderpath)
2548         {
2549         case RENDERPATH_D3D9:
2550 #ifdef SUPPORTD3D
2551                 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);
2552                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2553                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2554                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2555                 if (mode == SHADERMODE_LIGHTSOURCE)
2556                 {
2557                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2558                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2559                 }
2560                 else
2561                 {
2562                         if (mode == SHADERMODE_LIGHTDIRECTION)
2563                         {
2564                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2565                         }
2566                 }
2567                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2568                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2569                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2570                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2571                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2572
2573                 if (mode == SHADERMODE_LIGHTSOURCE)
2574                 {
2575                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2576                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2577                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2578                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2579                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2580
2581                         // additive passes are only darkened by fog, not tinted
2582                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2583                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2584                 }
2585                 else
2586                 {
2587                         if (mode == SHADERMODE_FLATCOLOR)
2588                         {
2589                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2590                         }
2591                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2592                         {
2593                                 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]);
2594                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2595                                 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);
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2597                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2598                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2599                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2600                         }
2601                         else
2602                         {
2603                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2604                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2605                                 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);
2606                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2607                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2608                         }
2609                         // additive passes are only darkened by fog, not tinted
2610                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2611                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2612                         else
2613                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2614                         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);
2615                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2616                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2617                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2618                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2619                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2620                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2621                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2622                         if (mode == SHADERMODE_WATER)
2623                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2624                 }
2625                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2626                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2627                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2628                 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));
2629                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2630                 if (rsurface.texture->pantstexture)
2631                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2632                 else
2633                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2634                 if (rsurface.texture->shirttexture)
2635                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2636                 else
2637                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2638                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2639                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2640                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2641                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2642                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2643                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2644                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2645                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2646                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2647                         );
2648                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2649                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2650                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2651                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2652
2653                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2654                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2655                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2656                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2657                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2658                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2659                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2660                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2661                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2662                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2663                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2664                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2665                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2666                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2667                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2668                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2669                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2670                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2671                 {
2672                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2673                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2674                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2675                 }
2676                 else
2677                 {
2678                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2679                 }
2680 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2681                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2682                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2683                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2684                 {
2685                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2686                         if (rsurface.rtlight)
2687                         {
2688                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2689                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2690                         }
2691                 }
2692 #endif
2693                 break;
2694         case RENDERPATH_D3D10:
2695                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2696                 break;
2697         case RENDERPATH_D3D11:
2698                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2699                 break;
2700         case RENDERPATH_GL20:
2701         case RENDERPATH_GLES2:
2702                 if (!vid.useinterleavedarrays)
2703                 {
2704                         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);
2705                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2706                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2707                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2708                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2709                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2710                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2711                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2712                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2713                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2714                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2715                 }
2716                 else
2717                 {
2718                         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);
2719                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2720                 }
2721                 // this has to be after RSurf_PrepareVerticesForBatch
2722                 if (rsurface.batchskeletaltransform3x4buffer)
2723                         permutation |= SHADERPERMUTATION_SKELETAL;
2724                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2725                 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);
2726                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2727                 if (mode == SHADERMODE_LIGHTSOURCE)
2728                 {
2729                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2730                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2731                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2732                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2733                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2734                         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);
2735         
2736                         // additive passes are only darkened by fog, not tinted
2737                         if (r_glsl_permutation->loc_FogColor >= 0)
2738                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2739                         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);
2740                 }
2741                 else
2742                 {
2743                         if (mode == SHADERMODE_FLATCOLOR)
2744                         {
2745                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2746                         }
2747                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2748                         {
2749                                 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]);
2750                                 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]);
2751                                 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);
2752                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2753                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2754                                 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]);
2755                                 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]);
2756                         }
2757                         else
2758                         {
2759                                 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]);
2760                                 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]);
2761                                 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);
2762                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2763                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2764                         }
2765                         // additive passes are only darkened by fog, not tinted
2766                         if (r_glsl_permutation->loc_FogColor >= 0)
2767                         {
2768                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2769                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2770                                 else
2771                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2772                         }
2773                         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);
2774                         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]);
2775                         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]);
2776                         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]);
2777                         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]);
2778                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2779                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2780                         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);
2781                         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]);
2782                 }
2783                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2784                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2785                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2786                 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]);
2787                 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]);
2788
2789                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2790                 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));
2791                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2792                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2793                 {
2794                         if (rsurface.texture->pantstexture)
2795                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2796                         else
2797                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2798                 }
2799                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2800                 {
2801                         if (rsurface.texture->shirttexture)
2802                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2803                         else
2804                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2805                 }
2806                 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]);
2807                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2808                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2809                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2810                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2811                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2812                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2813                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2814                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2815                         );
2816                 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);
2817                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2818                 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]);
2819                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2820                 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);}
2821                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2822
2823                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2824                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2825                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2826                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2827                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2828                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2829                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2830                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2831                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2832                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2833                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2834                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2835                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2836                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2837                 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);
2838                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2839                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2840                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2841                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2842                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2843                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2844                 {
2845                         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);
2846                         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);
2847                         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);
2848                 }
2849                 else
2850                 {
2851                         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);
2852                 }
2853                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2854                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2855                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2856                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2857                 {
2858                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2859                         if (rsurface.rtlight)
2860                         {
2861                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2862                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2863                         }
2864                 }
2865                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2866                 CHECKGLERROR
2867                 break;
2868         case RENDERPATH_GL11:
2869         case RENDERPATH_GL13:
2870         case RENDERPATH_GLES1:
2871                 break;
2872         case RENDERPATH_SOFT:
2873                 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);
2874                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2875                 R_SetupShader_SetPermutationSoft(mode, permutation);
2876                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2877                 if (mode == SHADERMODE_LIGHTSOURCE)
2878                 {
2879                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2880                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2881                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2882                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2883                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2884                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2885         
2886                         // additive passes are only darkened by fog, not tinted
2887                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2888                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2889                 }
2890                 else
2891                 {
2892                         if (mode == SHADERMODE_FLATCOLOR)
2893                         {
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2895                         }
2896                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2897                         {
2898                                 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]);
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2900                                 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);
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2903                                 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]);
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2905                         }
2906                         else
2907                         {
2908                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2909                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2910                                 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);
2911                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2912                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2913                         }
2914                         // additive passes are only darkened by fog, not tinted
2915                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2916                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2917                         else
2918                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2919                         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);
2920                         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]);
2921                         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]);
2922                         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]);
2923                         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]);
2924                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2925                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2926                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2927                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2928                 }
2929                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2930                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2931                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2932                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2933                 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]);
2934
2935                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2936                 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));
2937                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2938                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2939                 {
2940                         if (rsurface.texture->pantstexture)
2941                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2942                         else
2943                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2944                 }
2945                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2946                 {
2947                         if (rsurface.texture->shirttexture)
2948                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2949                         else
2950                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2951                 }
2952                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2953                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2954                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2955                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2956                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2957                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2958                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2959                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2960                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2961                         );
2962                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2963                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2964                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2965                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2966
2967                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2968                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2969                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2970                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2971                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2972                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2973                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2974                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2975                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2976                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2977                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2978                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2979                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2980                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2981                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2982                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2983                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2984                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2985                 {
2986                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2987                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2988                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2989                 }
2990                 else
2991                 {
2992                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2993                 }
2994 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2995                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2996                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2997                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2998                 {
2999                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3000                         if (rsurface.rtlight)
3001                         {
3002                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3003                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3004                         }
3005                 }
3006                 break;
3007         }
3008 }
3009
3010 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3011 {
3012         // select a permutation of the lighting shader appropriate to this
3013         // combination of texture, entity, light source, and fogging, only use the
3014         // minimum features necessary to avoid wasting rendering time in the
3015         // fragment shader on features that are not being used
3016         unsigned int permutation = 0;
3017         unsigned int mode = 0;
3018         const float *lightcolorbase = rtlight->currentcolor;
3019         float ambientscale = rtlight->ambientscale;
3020         float diffusescale = rtlight->diffusescale;
3021         float specularscale = rtlight->specularscale;
3022         // this is the location of the light in view space
3023         vec3_t viewlightorigin;
3024         // this transforms from view space (camera) to light space (cubemap)
3025         matrix4x4_t viewtolight;
3026         matrix4x4_t lighttoview;
3027         float viewtolight16f[16];
3028         // light source
3029         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3030         if (rtlight->currentcubemap != r_texture_whitecube)
3031                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3032         if (diffusescale > 0)
3033                 permutation |= SHADERPERMUTATION_DIFFUSE;
3034         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3035                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3036         if (r_shadow_usingshadowmap2d)
3037         {
3038                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3039                 if (r_shadow_shadowmapvsdct)
3040                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3041
3042                 if (r_shadow_shadowmap2ddepthbuffer)
3043                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3044         }
3045         if (vid.allowalphatocoverage)
3046                 GL_AlphaToCoverage(false);
3047         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3048         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3049         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3050         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3051         switch(vid.renderpath)
3052         {
3053         case RENDERPATH_D3D9:
3054 #ifdef SUPPORTD3D
3055                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3056                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3057                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3058                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3059                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3060                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3061                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3062                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3063                 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);
3064                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3065                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3066
3067                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3068                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3069                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3070                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3071                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3072 #endif
3073                 break;
3074         case RENDERPATH_D3D10:
3075                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3076                 break;
3077         case RENDERPATH_D3D11:
3078                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3079                 break;
3080         case RENDERPATH_GL20:
3081         case RENDERPATH_GLES2:
3082                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3083                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3084                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3085                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3086                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3087                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3088                 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]);
3089                 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]);
3090                 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);
3091                 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]);
3092                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3093
3094                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3095                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3096                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3097                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3098                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3099                 break;
3100         case RENDERPATH_GL11:
3101         case RENDERPATH_GL13:
3102         case RENDERPATH_GLES1:
3103                 break;
3104         case RENDERPATH_SOFT:
3105                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3106                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3107                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3108                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3109                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3110                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3111                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3112                 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]);
3113                 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);
3114                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3115                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3116
3117                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3118                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3119                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3120                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3121                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3122                 break;
3123         }
3124 }
3125
3126 #define SKINFRAME_HASH 1024
3127
3128 typedef struct
3129 {
3130         int loadsequence; // incremented each level change
3131         memexpandablearray_t array;
3132         skinframe_t *hash[SKINFRAME_HASH];
3133 }
3134 r_skinframe_t;
3135 r_skinframe_t r_skinframe;
3136
3137 void R_SkinFrame_PrepareForPurge(void)
3138 {
3139         r_skinframe.loadsequence++;
3140         // wrap it without hitting zero
3141         if (r_skinframe.loadsequence >= 200)
3142                 r_skinframe.loadsequence = 1;
3143 }
3144
3145 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3146 {
3147         if (!skinframe)
3148                 return;
3149         // mark the skinframe as used for the purging code
3150         skinframe->loadsequence = r_skinframe.loadsequence;
3151 }
3152
3153 void R_SkinFrame_Purge(void)
3154 {
3155         int i;
3156         skinframe_t *s;
3157         for (i = 0;i < SKINFRAME_HASH;i++)
3158         {
3159                 for (s = r_skinframe.hash[i];s;s = s->next)
3160                 {
3161                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3162                         {
3163                                 if (s->merged == s->base)
3164                                         s->merged = NULL;
3165                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3166                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3167                                 R_PurgeTexture(s->merged);s->merged = NULL;
3168                                 R_PurgeTexture(s->base  );s->base   = NULL;
3169                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3170                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3171                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3172                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3173                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3174                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3175                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3176                                 s->loadsequence = 0;
3177                         }
3178                 }
3179         }
3180 }
3181
3182 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3183         skinframe_t *item;
3184         char basename[MAX_QPATH];
3185
3186         Image_StripImageExtension(name, basename, sizeof(basename));
3187
3188         if( last == NULL ) {
3189                 int hashindex;
3190                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3191                 item = r_skinframe.hash[hashindex];
3192         } else {
3193                 item = last->next;
3194         }
3195
3196         // linearly search through the hash bucket
3197         for( ; item ; item = item->next ) {
3198                 if( !strcmp( item->basename, basename ) ) {
3199                         return item;
3200                 }
3201         }
3202         return NULL;
3203 }
3204
3205 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3206 {
3207         skinframe_t *item;
3208         int hashindex;
3209         char basename[MAX_QPATH];
3210
3211         Image_StripImageExtension(name, basename, sizeof(basename));
3212
3213         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3214         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3215                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3216                         break;
3217
3218         if (!item) {
3219                 rtexture_t *dyntexture;
3220                 // check whether its a dynamic texture
3221                 dyntexture = CL_GetDynTexture( basename );
3222                 if (!add && !dyntexture)
3223                         return NULL;
3224                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3225                 memset(item, 0, sizeof(*item));
3226                 strlcpy(item->basename, basename, sizeof(item->basename));
3227                 item->base = dyntexture; // either NULL or dyntexture handle
3228                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3229                 item->comparewidth = comparewidth;
3230                 item->compareheight = compareheight;
3231                 item->comparecrc = comparecrc;
3232                 item->next = r_skinframe.hash[hashindex];
3233                 r_skinframe.hash[hashindex] = item;
3234         }
3235         else if (textureflags & TEXF_FORCE_RELOAD)
3236         {
3237                 rtexture_t *dyntexture;
3238                 // check whether its a dynamic texture
3239                 dyntexture = CL_GetDynTexture( basename );
3240                 if (!add && !dyntexture)
3241                         return NULL;
3242                 if (item->merged == item->base)
3243                         item->merged = NULL;
3244                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3245                 R_PurgeTexture(item->stain );item->stain  = NULL;
3246                 R_PurgeTexture(item->merged);item->merged = NULL;
3247                 R_PurgeTexture(item->base  );item->base   = NULL;
3248                 R_PurgeTexture(item->pants );item->pants  = NULL;
3249                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3250                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3251                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3252                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3253                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3254         R_PurgeTexture(item->reflect);item->reflect = NULL;
3255                 item->loadsequence = 0;
3256         }
3257         else if( item->base == NULL )
3258         {
3259                 rtexture_t *dyntexture;
3260                 // check whether its a dynamic texture
3261                 // 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]
3262                 dyntexture = CL_GetDynTexture( basename );
3263                 item->base = dyntexture; // either NULL or dyntexture handle
3264         }
3265
3266         R_SkinFrame_MarkUsed(item);
3267         return item;
3268 }
3269
3270 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3271         { \
3272                 unsigned long long avgcolor[5], wsum; \
3273                 int pix, comp, w; \
3274                 avgcolor[0] = 0; \
3275                 avgcolor[1] = 0; \
3276                 avgcolor[2] = 0; \
3277                 avgcolor[3] = 0; \
3278                 avgcolor[4] = 0; \
3279                 wsum = 0; \
3280                 for(pix = 0; pix < cnt; ++pix) \
3281                 { \
3282                         w = 0; \
3283                         for(comp = 0; comp < 3; ++comp) \
3284                                 w += getpixel; \
3285                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3286                         { \
3287                                 ++wsum; \
3288                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3289                                 w = getpixel; \
3290                                 for(comp = 0; comp < 3; ++comp) \
3291                                         avgcolor[comp] += getpixel * w; \
3292                                 avgcolor[3] += w; \
3293                         } \
3294                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3295                         avgcolor[4] += getpixel; \
3296                 } \
3297                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3298                         avgcolor[3] = 1; \
3299                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3300                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3301                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3302                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3303         }
3304
3305 extern cvar_t gl_picmip;
3306 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3307 {
3308         int j;
3309         unsigned char *pixels;
3310         unsigned char *bumppixels;
3311         unsigned char *basepixels = NULL;
3312         int basepixels_width = 0;
3313         int basepixels_height = 0;
3314         skinframe_t *skinframe;
3315         rtexture_t *ddsbase = NULL;
3316         qboolean ddshasalpha = false;
3317         float ddsavgcolor[4];
3318         char basename[MAX_QPATH];
3319         int miplevel = R_PicmipForFlags(textureflags);
3320         int savemiplevel = miplevel;
3321         int mymiplevel;
3322         char vabuf[1024];
3323
3324         if (cls.state == ca_dedicated)
3325                 return NULL;
3326
3327         // return an existing skinframe if already loaded
3328         // if loading of the first image fails, don't make a new skinframe as it
3329         // would cause all future lookups of this to be missing
3330         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3331         if (skinframe && skinframe->base)
3332                 return skinframe;
3333
3334         Image_StripImageExtension(name, basename, sizeof(basename));
3335
3336         // check for DDS texture file first
3337         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3338         {
3339                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3340                 if (basepixels == NULL)
3341                         return NULL;
3342         }
3343
3344         // FIXME handle miplevel
3345
3346         if (developer_loading.integer)
3347                 Con_Printf("loading skin \"%s\"\n", name);
3348
3349         // we've got some pixels to store, so really allocate this new texture now
3350         if (!skinframe)
3351                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3352         textureflags &= ~TEXF_FORCE_RELOAD;
3353         skinframe->stain = NULL;
3354         skinframe->merged = NULL;
3355         skinframe->base = NULL;
3356         skinframe->pants = NULL;
3357         skinframe->shirt = NULL;
3358         skinframe->nmap = NULL;
3359         skinframe->gloss = NULL;
3360         skinframe->glow = NULL;
3361         skinframe->fog = NULL;
3362         skinframe->reflect = NULL;
3363         skinframe->hasalpha = false;
3364
3365         if (ddsbase)
3366         {
3367                 skinframe->base = ddsbase;
3368                 skinframe->hasalpha = ddshasalpha;
3369                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3370                 if (r_loadfog && skinframe->hasalpha)
3371                         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);
3372                 //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]);
3373         }
3374         else
3375         {
3376                 basepixels_width = image_width;
3377                 basepixels_height = image_height;
3378                 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);
3379                 if (textureflags & TEXF_ALPHA)
3380                 {
3381                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3382                         {
3383                                 if (basepixels[j] < 255)
3384                                 {
3385                                         skinframe->hasalpha = true;
3386                                         break;
3387                                 }
3388                         }
3389                         if (r_loadfog && skinframe->hasalpha)
3390                         {
3391                                 // has transparent pixels
3392                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3393                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3394                                 {
3395                                         pixels[j+0] = 255;
3396                                         pixels[j+1] = 255;
3397                                         pixels[j+2] = 255;
3398                                         pixels[j+3] = basepixels[j+3];
3399                                 }
3400                                 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);
3401                                 Mem_Free(pixels);
3402                         }
3403                 }
3404                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3405 #ifndef USE_GLES2
3406                 //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]);
3407                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3408                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3409                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3410                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3411 #endif
3412         }
3413
3414         if (r_loaddds)
3415         {
3416                 mymiplevel = savemiplevel;
3417                 if (r_loadnormalmap)
3418                         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);
3419                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3420                 if (r_loadgloss)
3421                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3422                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3423                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3424                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3425         }
3426
3427         // _norm is the name used by tenebrae and has been adopted as standard
3428         if (r_loadnormalmap && skinframe->nmap == NULL)
3429         {
3430                 mymiplevel = savemiplevel;
3431                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3432                 {
3433                         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);
3434                         Mem_Free(pixels);
3435                         pixels = NULL;
3436                 }
3437                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3438                 {
3439                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3440                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3441                         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);
3442                         Mem_Free(pixels);
3443                         Mem_Free(bumppixels);
3444                 }
3445                 else if (r_shadow_bumpscale_basetexture.value > 0)
3446                 {
3447                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3448                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3449                         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);
3450                         Mem_Free(pixels);
3451                 }
3452 #ifndef USE_GLES2
3453                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3454                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3455 #endif
3456         }
3457
3458         // _luma is supported only for tenebrae compatibility
3459         // _glow is the preferred name
3460         mymiplevel = savemiplevel;
3461         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))))
3462         {
3463                 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);
3464 #ifndef USE_GLES2
3465                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3466                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3467 #endif
3468                 Mem_Free(pixels);pixels = NULL;
3469         }
3470
3471         mymiplevel = savemiplevel;
3472         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3473         {
3474                 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);
3475 #ifndef USE_GLES2
3476                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3477                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3478 #endif
3479                 Mem_Free(pixels);
3480                 pixels = NULL;
3481         }
3482
3483         mymiplevel = savemiplevel;
3484         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3485         {
3486                 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);
3487 #ifndef USE_GLES2
3488                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3489                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3490 #endif
3491                 Mem_Free(pixels);
3492                 pixels = NULL;
3493         }
3494
3495         mymiplevel = savemiplevel;
3496         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3497         {
3498                 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);
3499 #ifndef USE_GLES2
3500                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3501                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3502 #endif
3503                 Mem_Free(pixels);
3504                 pixels = NULL;
3505         }
3506
3507         mymiplevel = savemiplevel;
3508         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3509         {
3510                 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);
3511 #ifndef USE_GLES2
3512                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3513                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3514 #endif
3515                 Mem_Free(pixels);
3516                 pixels = NULL;
3517         }
3518
3519         if (basepixels)
3520                 Mem_Free(basepixels);
3521
3522         return skinframe;
3523 }
3524
3525 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3526 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3527 {
3528         int i;
3529         unsigned char *temp1, *temp2;
3530         skinframe_t *skinframe;
3531         char vabuf[1024];
3532
3533         if (cls.state == ca_dedicated)
3534                 return NULL;
3535
3536         // if already loaded just return it, otherwise make a new skinframe
3537         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3538         if (skinframe->base)
3539                 return skinframe;
3540         textureflags &= ~TEXF_FORCE_RELOAD;
3541
3542         skinframe->stain = NULL;
3543         skinframe->merged = NULL;
3544         skinframe->base = NULL;
3545         skinframe->pants = NULL;
3546         skinframe->shirt = NULL;
3547         skinframe->nmap = NULL;
3548         skinframe->gloss = NULL;
3549         skinframe->glow = NULL;
3550         skinframe->fog = NULL;
3551         skinframe->reflect = NULL;
3552         skinframe->hasalpha = false;
3553
3554         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3555         if (!skindata)
3556                 return NULL;
3557
3558         if (developer_loading.integer)
3559                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3560
3561         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3562         {
3563                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3564                 temp2 = temp1 + width * height * 4;
3565                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3566                 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);
3567                 Mem_Free(temp1);
3568         }
3569         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3570         if (textureflags & TEXF_ALPHA)
3571         {
3572                 for (i = 3;i < width * height * 4;i += 4)
3573                 {
3574                         if (skindata[i] < 255)
3575                         {
3576                                 skinframe->hasalpha = true;
3577                                 break;
3578                         }
3579                 }
3580                 if (r_loadfog && skinframe->hasalpha)
3581                 {
3582                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3583                         memcpy(fogpixels, skindata, width * height * 4);
3584                         for (i = 0;i < width * height * 4;i += 4)
3585                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3586                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3587                         Mem_Free(fogpixels);
3588                 }
3589         }
3590
3591         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3592         //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]);
3593
3594         return skinframe;
3595 }
3596
3597 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3598 {
3599         int i;
3600         int featuresmask;
3601         skinframe_t *skinframe;
3602
3603         if (cls.state == ca_dedicated)
3604                 return NULL;
3605
3606         // if already loaded just return it, otherwise make a new skinframe
3607         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3608         if (skinframe->base)
3609                 return skinframe;
3610         //textureflags &= ~TEXF_FORCE_RELOAD;
3611
3612         skinframe->stain = NULL;
3613         skinframe->merged = NULL;
3614         skinframe->base = NULL;
3615         skinframe->pants = NULL;
3616         skinframe->shirt = NULL;
3617         skinframe->nmap = NULL;
3618         skinframe->gloss = NULL;
3619         skinframe->glow = NULL;
3620         skinframe->fog = NULL;
3621         skinframe->reflect = NULL;
3622         skinframe->hasalpha = false;
3623
3624         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3625         if (!skindata)
3626                 return NULL;
3627
3628         if (developer_loading.integer)
3629                 Con_Printf("loading quake skin \"%s\"\n", name);
3630
3631         // 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)
3632         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3633         memcpy(skinframe->qpixels, skindata, width*height);
3634         skinframe->qwidth = width;
3635         skinframe->qheight = height;
3636
3637         featuresmask = 0;
3638         for (i = 0;i < width * height;i++)
3639                 featuresmask |= palette_featureflags[skindata[i]];
3640
3641         skinframe->hasalpha = false;
3642         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3643         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3644         skinframe->qgeneratemerged = true;
3645         skinframe->qgeneratebase = skinframe->qhascolormapping;
3646         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3647
3648         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3649         //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]);
3650
3651         return skinframe;
3652 }
3653
3654 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3655 {
3656         int width;
3657         int height;
3658         unsigned char *skindata;
3659         char vabuf[1024];
3660
3661         if (!skinframe->qpixels)
3662                 return;
3663
3664         if (!skinframe->qhascolormapping)
3665                 colormapped = false;
3666
3667         if (colormapped)
3668         {
3669                 if (!skinframe->qgeneratebase)
3670                         return;
3671         }
3672         else
3673         {
3674                 if (!skinframe->qgeneratemerged)
3675                         return;
3676         }
3677
3678         width = skinframe->qwidth;
3679         height = skinframe->qheight;
3680         skindata = skinframe->qpixels;
3681
3682         if (skinframe->qgeneratenmap)
3683         {
3684                 unsigned char *temp1, *temp2;
3685                 skinframe->qgeneratenmap = false;
3686                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3687                 temp2 = temp1 + width * height * 4;
3688                 // use either a custom palette or the quake palette
3689                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3690                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3691                 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);
3692                 Mem_Free(temp1);
3693         }
3694
3695         if (skinframe->qgenerateglow)
3696         {
3697                 skinframe->qgenerateglow = false;
3698                 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
3699         }
3700
3701         if (colormapped)
3702         {
3703                 skinframe->qgeneratebase = false;
3704                 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);
3705                 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);
3706                 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);
3707         }
3708         else
3709         {
3710                 skinframe->qgeneratemerged = false;
3711                 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);
3712         }
3713
3714         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3715         {
3716                 Mem_Free(skinframe->qpixels);
3717                 skinframe->qpixels = NULL;
3718         }
3719 }
3720
3721 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)
3722 {
3723         int i;
3724         skinframe_t *skinframe;
3725         char vabuf[1024];
3726
3727         if (cls.state == ca_dedicated)
3728                 return NULL;
3729
3730         // if already loaded just return it, otherwise make a new skinframe
3731         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3732         if (skinframe->base)
3733                 return skinframe;
3734         textureflags &= ~TEXF_FORCE_RELOAD;
3735
3736         skinframe->stain = NULL;
3737         skinframe->merged = NULL;
3738         skinframe->base = NULL;
3739         skinframe->pants = NULL;
3740         skinframe->shirt = NULL;
3741         skinframe->nmap = NULL;
3742         skinframe->gloss = NULL;
3743         skinframe->glow = NULL;
3744         skinframe->fog = NULL;
3745         skinframe->reflect = NULL;
3746         skinframe->hasalpha = false;
3747
3748         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3749         if (!skindata)
3750                 return NULL;
3751
3752         if (developer_loading.integer)
3753                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3754
3755         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3756         if (textureflags & TEXF_ALPHA)
3757         {
3758                 for (i = 0;i < width * height;i++)
3759                 {
3760                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3761                         {
3762                                 skinframe->hasalpha = true;
3763                                 break;
3764                         }
3765                 }
3766                 if (r_loadfog && skinframe->hasalpha)
3767                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3768         }
3769
3770         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3771         //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]);
3772
3773         return skinframe;
3774 }
3775
3776 skinframe_t *R_SkinFrame_LoadMissing(void)
3777 {
3778         skinframe_t *skinframe;
3779
3780         if (cls.state == ca_dedicated)
3781                 return NULL;
3782
3783         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3784         skinframe->stain = NULL;
3785         skinframe->merged = NULL;
3786         skinframe->base = NULL;
3787         skinframe->pants = NULL;
3788         skinframe->shirt = NULL;
3789         skinframe->nmap = NULL;
3790         skinframe->gloss = NULL;
3791         skinframe->glow = NULL;
3792         skinframe->fog = NULL;
3793         skinframe->reflect = NULL;
3794         skinframe->hasalpha = false;
3795
3796         skinframe->avgcolor[0] = rand() / RAND_MAX;
3797         skinframe->avgcolor[1] = rand() / RAND_MAX;
3798         skinframe->avgcolor[2] = rand() / RAND_MAX;
3799         skinframe->avgcolor[3] = 1;
3800
3801         return skinframe;
3802 }
3803
3804 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3805 typedef struct suffixinfo_s
3806 {
3807         const char *suffix;
3808         qboolean flipx, flipy, flipdiagonal;
3809 }
3810 suffixinfo_t;
3811 static suffixinfo_t suffix[3][6] =
3812 {
3813         {
3814                 {"px",   false, false, false},
3815                 {"nx",   false, false, false},
3816                 {"py",   false, false, false},
3817                 {"ny",   false, false, false},
3818                 {"pz",   false, false, false},
3819                 {"nz",   false, false, false}
3820         },
3821         {
3822                 {"posx", false, false, false},
3823                 {"negx", false, false, false},
3824                 {"posy", false, false, false},
3825                 {"negy", false, false, false},
3826                 {"posz", false, false, false},
3827                 {"negz", false, false, false}
3828         },
3829         {
3830                 {"rt",    true, false,  true},
3831                 {"lf",   false,  true,  true},
3832                 {"ft",    true,  true, false},
3833                 {"bk",   false, false, false},
3834                 {"up",    true, false,  true},
3835                 {"dn",    true, false,  true}
3836         }
3837 };
3838
3839 static int componentorder[4] = {0, 1, 2, 3};
3840
3841 static rtexture_t *R_LoadCubemap(const char *basename)
3842 {
3843         int i, j, cubemapsize;
3844         unsigned char *cubemappixels, *image_buffer;
3845         rtexture_t *cubemaptexture;
3846         char name[256];
3847         // must start 0 so the first loadimagepixels has no requested width/height
3848         cubemapsize = 0;
3849         cubemappixels = NULL;
3850         cubemaptexture = NULL;
3851         // keep trying different suffix groups (posx, px, rt) until one loads
3852         for (j = 0;j < 3 && !cubemappixels;j++)
3853         {
3854                 // load the 6 images in the suffix group
3855                 for (i = 0;i < 6;i++)
3856                 {
3857                         // generate an image name based on the base and and suffix
3858                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3859                         // load it
3860                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3861                         {
3862                                 // an image loaded, make sure width and height are equal
3863                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3864                                 {
3865                                         // if this is the first image to load successfully, allocate the cubemap memory
3866                                         if (!cubemappixels && image_width >= 1)
3867                                         {
3868                                                 cubemapsize = image_width;
3869                                                 // note this clears to black, so unavailable sides are black
3870                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3871                                         }
3872                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3873                                         if (cubemappixels)
3874                                                 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);
3875                                 }
3876                                 else
3877                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3878                                 // free the image
3879                                 Mem_Free(image_buffer);
3880                         }
3881                 }
3882         }
3883         // if a cubemap loaded, upload it
3884         if (cubemappixels)
3885         {
3886                 if (developer_loading.integer)
3887                         Con_Printf("loading cubemap \"%s\"\n", basename);
3888
3889                 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);
3890                 Mem_Free(cubemappixels);
3891         }
3892         else
3893         {
3894                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3895                 if (developer_loading.integer)
3896                 {
3897                         Con_Printf("(tried tried images ");
3898                         for (j = 0;j < 3;j++)
3899                                 for (i = 0;i < 6;i++)
3900                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3901                         Con_Print(" and was unable to find any of them).\n");
3902                 }
3903         }
3904         return cubemaptexture;
3905 }
3906
3907 rtexture_t *R_GetCubemap(const char *basename)
3908 {
3909         int i;
3910         for (i = 0;i < r_texture_numcubemaps;i++)
3911                 if (r_texture_cubemaps[i] != NULL)
3912                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3913                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3914         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3915                 return r_texture_whitecube;
3916         r_texture_numcubemaps++;
3917         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3918         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3919         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3920         return r_texture_cubemaps[i]->texture;
3921 }
3922
3923 static void R_Main_FreeViewCache(void)
3924 {
3925         if (r_refdef.viewcache.entityvisible)
3926                 Mem_Free(r_refdef.viewcache.entityvisible);
3927         if (r_refdef.viewcache.world_pvsbits)
3928                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3929         if (r_refdef.viewcache.world_leafvisible)
3930                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3931         if (r_refdef.viewcache.world_surfacevisible)
3932                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3933         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3934 }
3935
3936 static void R_Main_ResizeViewCache(void)
3937 {
3938         int numentities = r_refdef.scene.numentities;
3939         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3940         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3941         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3942         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3943         if (r_refdef.viewcache.maxentities < numentities)
3944         {
3945                 r_refdef.viewcache.maxentities = numentities;
3946                 if (r_refdef.viewcache.entityvisible)
3947                         Mem_Free(r_refdef.viewcache.entityvisible);
3948                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3949         }
3950         if (r_refdef.viewcache.world_numclusters != numclusters)
3951         {
3952                 r_refdef.viewcache.world_numclusters = numclusters;
3953                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3954                 if (r_refdef.viewcache.world_pvsbits)
3955                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3956                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3957         }
3958         if (r_refdef.viewcache.world_numleafs != numleafs)
3959         {
3960                 r_refdef.viewcache.world_numleafs = numleafs;
3961                 if (r_refdef.viewcache.world_leafvisible)
3962                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3963                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3964         }
3965         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3966         {
3967                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3968                 if (r_refdef.viewcache.world_surfacevisible)
3969                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3970                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3971         }
3972 }
3973
3974 extern rtexture_t *loadingscreentexture;
3975 static void gl_main_start(void)
3976 {
3977         loadingscreentexture = NULL;
3978         r_texture_blanknormalmap = NULL;
3979         r_texture_white = NULL;
3980         r_texture_grey128 = NULL;
3981         r_texture_black = NULL;
3982         r_texture_whitecube = NULL;
3983         r_texture_normalizationcube = NULL;
3984         r_texture_fogattenuation = NULL;
3985         r_texture_fogheighttexture = NULL;
3986         r_texture_gammaramps = NULL;
3987         r_texture_numcubemaps = 0;
3988         r_uniformbufferalignment = 32;
3989
3990         r_loaddds = r_texture_dds_load.integer != 0;
3991         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3992
3993         switch(vid.renderpath)
3994         {
3995         case RENDERPATH_GL20:
3996         case RENDERPATH_D3D9:
3997         case RENDERPATH_D3D10:
3998         case RENDERPATH_D3D11:
3999         case RENDERPATH_SOFT:
4000         case RENDERPATH_GLES2:
4001                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4002                 Cvar_SetValueQuick(&gl_combine, 1);
4003                 Cvar_SetValueQuick(&r_glsl, 1);
4004                 r_loadnormalmap = true;
4005                 r_loadgloss = true;
4006                 r_loadfog = false;
4007                 if (vid.support.arb_uniform_buffer_object)
4008                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4009                 break;
4010         case RENDERPATH_GL13:
4011         case RENDERPATH_GLES1:
4012                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4013                 Cvar_SetValueQuick(&gl_combine, 1);
4014                 Cvar_SetValueQuick(&r_glsl, 0);
4015                 r_loadnormalmap = false;
4016                 r_loadgloss = false;
4017                 r_loadfog = true;
4018                 break;
4019         case RENDERPATH_GL11:
4020                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4021                 Cvar_SetValueQuick(&gl_combine, 0);
4022                 Cvar_SetValueQuick(&r_glsl, 0);
4023                 r_loadnormalmap = false;
4024                 r_loadgloss = false;
4025                 r_loadfog = true;
4026                 break;
4027         }
4028
4029         R_AnimCache_Free();
4030         R_FrameData_Reset();
4031         R_BufferData_Reset();
4032
4033         r_numqueries = 0;
4034         r_maxqueries = 0;
4035         memset(r_queries, 0, sizeof(r_queries));
4036
4037         r_qwskincache = NULL;
4038         r_qwskincache_size = 0;
4039
4040         // due to caching of texture_t references, the collision cache must be reset
4041         Collision_Cache_Reset(true);
4042
4043         // set up r_skinframe loading system for textures
4044         memset(&r_skinframe, 0, sizeof(r_skinframe));
4045         r_skinframe.loadsequence = 1;
4046         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4047
4048         r_main_texturepool = R_AllocTexturePool();
4049         R_BuildBlankTextures();
4050         R_BuildNoTexture();
4051         if (vid.support.arb_texture_cube_map)
4052         {
4053                 R_BuildWhiteCube();
4054                 R_BuildNormalizationCube();
4055         }
4056         r_texture_fogattenuation = NULL;
4057         r_texture_fogheighttexture = NULL;
4058         r_texture_gammaramps = NULL;
4059         //r_texture_fogintensity = NULL;
4060         memset(&r_fb, 0, sizeof(r_fb));
4061         r_glsl_permutation = NULL;
4062         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4063         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4064         glslshaderstring = NULL;
4065 #ifdef SUPPORTD3D
4066         r_hlsl_permutation = NULL;
4067         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4068         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4069 #endif
4070         hlslshaderstring = NULL;
4071         memset(&r_svbsp, 0, sizeof (r_svbsp));
4072
4073         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4074         r_texture_numcubemaps = 0;
4075
4076         r_refdef.fogmasktable_density = 0;
4077 }
4078
4079 static void gl_main_shutdown(void)
4080 {
4081         R_AnimCache_Free();
4082         R_FrameData_Reset();
4083         R_BufferData_Reset();
4084
4085         R_Main_FreeViewCache();
4086
4087         switch(vid.renderpath)
4088         {
4089         case RENDERPATH_GL11:
4090         case RENDERPATH_GL13:
4091         case RENDERPATH_GL20:
4092         case RENDERPATH_GLES1:
4093         case RENDERPATH_GLES2:
4094 #ifdef GL_SAMPLES_PASSED_ARB
4095                 if (r_maxqueries)
4096                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4097 #endif
4098                 break;
4099         case RENDERPATH_D3D9:
4100                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4101                 break;
4102         case RENDERPATH_D3D10:
4103                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4104                 break;
4105         case RENDERPATH_D3D11:
4106                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4107                 break;
4108         case RENDERPATH_SOFT:
4109                 break;
4110         }
4111
4112         r_numqueries = 0;
4113         r_maxqueries = 0;
4114         memset(r_queries, 0, sizeof(r_queries));
4115
4116         r_qwskincache = NULL;
4117         r_qwskincache_size = 0;
4118
4119         // clear out the r_skinframe state
4120         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4121         memset(&r_skinframe, 0, sizeof(r_skinframe));
4122
4123         if (r_svbsp.nodes)
4124                 Mem_Free(r_svbsp.nodes);
4125         memset(&r_svbsp, 0, sizeof (r_svbsp));
4126         R_FreeTexturePool(&r_main_texturepool);
4127         loadingscreentexture = NULL;
4128         r_texture_blanknormalmap = NULL;
4129         r_texture_white = NULL;
4130         r_texture_grey128 = NULL;
4131         r_texture_black = NULL;
4132         r_texture_whitecube = NULL;
4133         r_texture_normalizationcube = NULL;
4134         r_texture_fogattenuation = NULL;
4135         r_texture_fogheighttexture = NULL;
4136         r_texture_gammaramps = NULL;
4137         r_texture_numcubemaps = 0;
4138         //r_texture_fogintensity = NULL;
4139         memset(&r_fb, 0, sizeof(r_fb));
4140         R_GLSL_Restart_f();
4141
4142         r_glsl_permutation = NULL;
4143         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4144         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4145         glslshaderstring = NULL;
4146 #ifdef SUPPORTD3D
4147         r_hlsl_permutation = NULL;
4148         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4149         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4150 #endif
4151         hlslshaderstring = NULL;
4152 }
4153
4154 static void gl_main_newmap(void)
4155 {
4156         // FIXME: move this code to client
4157         char *entities, entname[MAX_QPATH];
4158         if (r_qwskincache)
4159                 Mem_Free(r_qwskincache);
4160         r_qwskincache = NULL;
4161         r_qwskincache_size = 0;
4162         if (cl.worldmodel)
4163         {
4164                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4165                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4166                 {
4167                         CL_ParseEntityLump(entities);
4168                         Mem_Free(entities);
4169                         return;
4170                 }
4171                 if (cl.worldmodel->brush.entities)
4172                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4173         }
4174         R_Main_FreeViewCache();
4175
4176         R_FrameData_Reset();
4177         R_BufferData_Reset();
4178 }
4179
4180 void GL_Main_Init(void)
4181 {
4182         int i;
4183         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4184
4185         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4186         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4187         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4188         if (gamemode == GAME_NEHAHRA)
4189         {
4190                 Cvar_RegisterVariable (&gl_fogenable);
4191                 Cvar_RegisterVariable (&gl_fogdensity);
4192                 Cvar_RegisterVariable (&gl_fogred);
4193                 Cvar_RegisterVariable (&gl_foggreen);
4194                 Cvar_RegisterVariable (&gl_fogblue);
4195                 Cvar_RegisterVariable (&gl_fogstart);
4196                 Cvar_RegisterVariable (&gl_fogend);
4197                 Cvar_RegisterVariable (&gl_skyclip);
4198         }
4199         Cvar_RegisterVariable(&r_motionblur);
4200         Cvar_RegisterVariable(&r_damageblur);
4201         Cvar_RegisterVariable(&r_motionblur_averaging);
4202         Cvar_RegisterVariable(&r_motionblur_randomize);
4203         Cvar_RegisterVariable(&r_motionblur_minblur);
4204         Cvar_RegisterVariable(&r_motionblur_maxblur);
4205         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4206         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4207         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4208         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4209         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4210         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4211         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4212         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4213         Cvar_RegisterVariable(&r_equalize_entities_by);
4214         Cvar_RegisterVariable(&r_equalize_entities_to);
4215         Cvar_RegisterVariable(&r_depthfirst);
4216         Cvar_RegisterVariable(&r_useinfinitefarclip);
4217         Cvar_RegisterVariable(&r_farclip_base);
4218         Cvar_RegisterVariable(&r_farclip_world);
4219         Cvar_RegisterVariable(&r_nearclip);
4220         Cvar_RegisterVariable(&r_deformvertexes);
4221         Cvar_RegisterVariable(&r_transparent);
4222         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4223         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4224         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4225         Cvar_RegisterVariable(&r_showoverdraw);
4226         Cvar_RegisterVariable(&r_showbboxes);
4227         Cvar_RegisterVariable(&r_showsurfaces);
4228         Cvar_RegisterVariable(&r_showtris);
4229         Cvar_RegisterVariable(&r_shownormals);
4230         Cvar_RegisterVariable(&r_showlighting);
4231         Cvar_RegisterVariable(&r_showshadowvolumes);
4232         Cvar_RegisterVariable(&r_showcollisionbrushes);
4233         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4234         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4235         Cvar_RegisterVariable(&r_showdisabledepthtest);
4236         Cvar_RegisterVariable(&r_drawportals);
4237         Cvar_RegisterVariable(&r_drawentities);
4238         Cvar_RegisterVariable(&r_draw2d);
4239         Cvar_RegisterVariable(&r_drawworld);
4240         Cvar_RegisterVariable(&r_cullentities_trace);
4241         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4242         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4243         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4244         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4245         Cvar_RegisterVariable(&r_sortentities);
4246         Cvar_RegisterVariable(&r_drawviewmodel);
4247         Cvar_RegisterVariable(&r_drawexteriormodel);
4248         Cvar_RegisterVariable(&r_speeds);
4249         Cvar_RegisterVariable(&r_fullbrights);
4250         Cvar_RegisterVariable(&r_wateralpha);
4251         Cvar_RegisterVariable(&r_dynamic);
4252         Cvar_RegisterVariable(&r_fakelight);
4253         Cvar_RegisterVariable(&r_fakelight_intensity);
4254         Cvar_RegisterVariable(&r_fullbright);
4255         Cvar_RegisterVariable(&r_shadows);
4256         Cvar_RegisterVariable(&r_shadows_darken);
4257         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4258         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4259         Cvar_RegisterVariable(&r_shadows_throwdistance);
4260         Cvar_RegisterVariable(&r_shadows_throwdirection);
4261         Cvar_RegisterVariable(&r_shadows_focus);
4262         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4263         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4264         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4265         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4266         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4267         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4268         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4269         Cvar_RegisterVariable(&r_fog_exp2);
4270         Cvar_RegisterVariable(&r_fog_clear);
4271         Cvar_RegisterVariable(&r_drawfog);
4272         Cvar_RegisterVariable(&r_transparentdepthmasking);
4273         Cvar_RegisterVariable(&r_transparent_sortmindist);
4274         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4275         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4276         Cvar_RegisterVariable(&r_texture_dds_load);
4277         Cvar_RegisterVariable(&r_texture_dds_save);
4278         Cvar_RegisterVariable(&r_textureunits);
4279         Cvar_RegisterVariable(&gl_combine);
4280         Cvar_RegisterVariable(&r_usedepthtextures);
4281         Cvar_RegisterVariable(&r_viewfbo);
4282         Cvar_RegisterVariable(&r_viewscale);
4283         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4284         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4285         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4286         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4287         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4288         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4289         Cvar_RegisterVariable(&r_glsl);
4290         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4291         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4292         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4293         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4294         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4295         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4296         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4297         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4298         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4299         Cvar_RegisterVariable(&r_glsl_postprocess);
4300         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4301         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4302         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4303         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4304         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4305         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4306         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4307         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4308         Cvar_RegisterVariable(&r_celshading);
4309         Cvar_RegisterVariable(&r_celoutlines);
4310
4311         Cvar_RegisterVariable(&r_water);
4312         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4313         Cvar_RegisterVariable(&r_water_clippingplanebias);
4314         Cvar_RegisterVariable(&r_water_refractdistort);
4315         Cvar_RegisterVariable(&r_water_reflectdistort);
4316         Cvar_RegisterVariable(&r_water_scissormode);
4317         Cvar_RegisterVariable(&r_water_lowquality);
4318         Cvar_RegisterVariable(&r_water_hideplayer);
4319         Cvar_RegisterVariable(&r_water_fbo);
4320
4321         Cvar_RegisterVariable(&r_lerpsprites);
4322         Cvar_RegisterVariable(&r_lerpmodels);
4323         Cvar_RegisterVariable(&r_lerplightstyles);
4324         Cvar_RegisterVariable(&r_waterscroll);
4325         Cvar_RegisterVariable(&r_bloom);
4326         Cvar_RegisterVariable(&r_bloom_colorscale);
4327         Cvar_RegisterVariable(&r_bloom_brighten);
4328         Cvar_RegisterVariable(&r_bloom_blur);
4329         Cvar_RegisterVariable(&r_bloom_resolution);
4330         Cvar_RegisterVariable(&r_bloom_colorexponent);
4331         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4332         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4333         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4334         Cvar_RegisterVariable(&r_hdr_glowintensity);
4335         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4336         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4337         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4338         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4339         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4340         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4341         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4342         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4343         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4344         Cvar_RegisterVariable(&developer_texturelogging);
4345         Cvar_RegisterVariable(&gl_lightmaps);
4346         Cvar_RegisterVariable(&r_test);
4347         Cvar_RegisterVariable(&r_batch_multidraw);
4348         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4349         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4350         Cvar_RegisterVariable(&r_glsl_skeletal);
4351         Cvar_RegisterVariable(&r_glsl_saturation);
4352         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4353         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4354         Cvar_RegisterVariable(&r_framedatasize);
4355         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4356                 Cvar_RegisterVariable(&r_bufferdatasize[i]);
4357         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4358         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4359                 Cvar_SetValue("r_fullbrights", 0);
4360         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4361 }
4362
4363 void Render_Init(void)
4364 {
4365         gl_backend_init();
4366         R_Textures_Init();
4367         GL_Main_Init();
4368         Font_Init();
4369         GL_Draw_Init();
4370         R_Shadow_Init();
4371         R_Sky_Init();
4372         GL_Surf_Init();
4373         Sbar_Init();
4374         R_Particles_Init();
4375         R_Explosion_Init();
4376         R_LightningBeams_Init();
4377         Mod_RenderInit();
4378 }
4379
4380 /*
4381 ===============
4382 GL_Init
4383 ===============
4384 */
4385 #ifndef USE_GLES2
4386 extern char *ENGINE_EXTENSIONS;
4387 void GL_Init (void)
4388 {
4389         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4390         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4391         gl_version = (const char *)qglGetString(GL_VERSION);
4392         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4393
4394         if (!gl_extensions)
4395                 gl_extensions = "";
4396         if (!gl_platformextensions)
4397                 gl_platformextensions = "";
4398
4399         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4400         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4401         Con_Printf("GL_VERSION: %s\n", gl_version);
4402         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4403         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4404
4405         VID_CheckExtensions();
4406
4407         // LordHavoc: report supported extensions
4408         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4409
4410         // clear to black (loading plaque will be seen over this)
4411         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4412 }
4413 #endif
4414
4415 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4416 {
4417         int i;
4418         mplane_t *p;
4419         if (r_trippy.integer)
4420                 return false;
4421         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4422         {
4423                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4424                 if (i == 4)
4425                         continue;
4426                 p = r_refdef.view.frustum + i;
4427                 switch(p->signbits)
4428                 {
4429                 default:
4430                 case 0:
4431                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4432                                 return true;
4433                         break;
4434                 case 1:
4435                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4436                                 return true;
4437                         break;
4438                 case 2:
4439                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4440                                 return true;
4441                         break;
4442                 case 3:
4443                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4444                                 return true;
4445                         break;
4446                 case 4:
4447                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4448                                 return true;
4449                         break;
4450                 case 5:
4451                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4452                                 return true;
4453                         break;
4454                 case 6:
4455                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4456                                 return true;
4457                         break;
4458                 case 7:
4459                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4460                                 return true;
4461                         break;
4462                 }
4463         }
4464         return false;
4465 }
4466
4467 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4468 {
4469         int i;
4470         const mplane_t *p;
4471         if (r_trippy.integer)
4472                 return false;
4473         for (i = 0;i < numplanes;i++)
4474         {
4475                 p = planes + i;
4476                 switch(p->signbits)
4477                 {
4478                 default:
4479                 case 0:
4480                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4481                                 return true;
4482                         break;
4483                 case 1:
4484                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4485                                 return true;
4486                         break;
4487                 case 2:
4488                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4489                                 return true;
4490                         break;
4491                 case 3:
4492                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4493                                 return true;
4494                         break;
4495                 case 4:
4496                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4497                                 return true;
4498                         break;
4499                 case 5:
4500                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4501                                 return true;
4502                         break;
4503                 case 6:
4504                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4505                                 return true;
4506                         break;
4507                 case 7:
4508                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4509                                 return true;
4510                         break;
4511                 }
4512         }
4513         return false;
4514 }
4515
4516 //==================================================================================
4517
4518 // LordHavoc: this stores temporary data used within the same frame
4519
4520 typedef struct r_framedata_mem_s
4521 {
4522         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4523         size_t size; // how much usable space
4524         size_t current; // how much space in use
4525         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4526         size_t wantedsize; // how much space was allocated
4527         unsigned char *data; // start of real data (16byte aligned)
4528 }
4529 r_framedata_mem_t;
4530
4531 static r_framedata_mem_t *r_framedata_mem;
4532
4533 void R_FrameData_Reset(void)
4534 {
4535         while (r_framedata_mem)
4536         {
4537                 r_framedata_mem_t *next = r_framedata_mem->purge;
4538                 Mem_Free(r_framedata_mem);
4539                 r_framedata_mem = next;
4540         }
4541 }
4542
4543 static void R_FrameData_Resize(qboolean mustgrow)
4544 {
4545         size_t wantedsize;
4546         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4547         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4548         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4549         {
4550                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4551                 newmem->wantedsize = wantedsize;
4552                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4553                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4554                 newmem->current = 0;
4555                 newmem->mark = 0;
4556                 newmem->purge = r_framedata_mem;
4557                 r_framedata_mem = newmem;
4558         }
4559 }
4560
4561 void R_FrameData_NewFrame(void)
4562 {
4563         R_FrameData_Resize(false);
4564         if (!r_framedata_mem)
4565                 return;
4566         // if we ran out of space on the last frame, free the old memory now
4567         while (r_framedata_mem->purge)
4568         {
4569                 // repeatedly remove the second item in the list, leaving only head
4570                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4571                 Mem_Free(r_framedata_mem->purge);
4572                 r_framedata_mem->purge = next;
4573         }
4574         // reset the current mem pointer
4575         r_framedata_mem->current = 0;
4576         r_framedata_mem->mark = 0;
4577 }
4578
4579 void *R_FrameData_Alloc(size_t size)
4580 {
4581         void *data;
4582         float newvalue;
4583
4584         // align to 16 byte boundary - the data pointer is already aligned, so we
4585         // only need to ensure the size of every allocation is also aligned
4586         size = (size + 15) & ~15;
4587
4588         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4589         {
4590                 // emergency - we ran out of space, allocate more memory
4591                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4592                 // this might not be a growing it, but we'll allocate another buffer every time
4593                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4594                 R_FrameData_Resize(true);
4595         }
4596
4597         data = r_framedata_mem->data + r_framedata_mem->current;
4598         r_framedata_mem->current += size;
4599
4600         // count the usage for stats
4601         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4602         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4603
4604         return (void *)data;
4605 }
4606
4607 void *R_FrameData_Store(size_t size, void *data)
4608 {
4609         void *d = R_FrameData_Alloc(size);
4610         if (d && data)
4611                 memcpy(d, data, size);
4612         return d;
4613 }
4614
4615 void R_FrameData_SetMark(void)
4616 {
4617         if (!r_framedata_mem)
4618                 return;
4619         r_framedata_mem->mark = r_framedata_mem->current;
4620 }
4621
4622 void R_FrameData_ReturnToMark(void)
4623 {
4624         if (!r_framedata_mem)
4625                 return;
4626         r_framedata_mem->current = r_framedata_mem->mark;
4627 }
4628
4629 //==================================================================================
4630
4631 // avoid reusing the same buffer objects on consecutive buffers
4632 #define R_BUFFERDATA_CYCLE 2
4633
4634 typedef struct r_bufferdata_buffer_s
4635 {
4636         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4637         size_t size; // how much usable space
4638         size_t current; // how much space in use
4639         r_meshbuffer_t *buffer; // the buffer itself
4640 }
4641 r_bufferdata_buffer_t;
4642
4643 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4644 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4645
4646 /// frees all dynamic buffers
4647 void R_BufferData_Reset(void)
4648 {
4649         int cycle, type;
4650         r_bufferdata_buffer_t **p, *mem;
4651         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4652         {
4653                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4654                 {
4655                         // free all buffers
4656                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type];
4657                         while (*p)
4658                         {
4659                                 mem = *p;
4660                                 *p = (*p)->purge;
4661                                 if (mem->buffer)
4662                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4663                                 Mem_Free(mem);
4664                         }
4665                 }
4666         }
4667 }
4668
4669 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4670 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow)
4671 {
4672         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4673         size_t size;
4674         size = (size_t)(r_bufferdatasize[type].value * 1024*1024);
4675         size = bound(65536, size, 512*1024*1024);
4676         if (!mem || mem->size != size || mustgrow)
4677         {
4678                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4679                 mem->size = size;
4680                 mem->current = 0;
4681                 if (type == R_BUFFERDATA_VERTEX)
4682                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4683                 else if (type == R_BUFFERDATA_INDEX16)
4684                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4685                 else if (type == R_BUFFERDATA_INDEX32)
4686                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4687                 else if (type == R_BUFFERDATA_UNIFORM)
4688                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4689                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4690                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4691         }
4692 }
4693
4694 void R_BufferData_NewFrame(void)
4695 {
4696         int type;
4697         r_bufferdata_buffer_t **p, *mem;
4698         // cycle to the next frame's buffers
4699         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4700         // if we ran out of space on the last time we used these buffers, free the old memory now
4701         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4702         {
4703                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4704                 {
4705                         R_BufferData_Resize((r_bufferdata_type_t)type, false);
4706                         // free all but the head buffer, this is how we recycle obsolete
4707                         // buffers after they are no longer in use
4708                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4709                         while (*p)
4710                         {
4711                                 mem = *p;
4712                                 *p = (*p)->purge;
4713                                 if (mem->buffer)
4714                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4715                                 Mem_Free(mem);
4716                         }
4717                         // reset the current offset
4718                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4719                 }
4720         }
4721 }
4722
4723 r_meshbuffer_t *R_BufferData_Store(size_t datasize, void *data, r_bufferdata_type_t type, int *returnbufferoffset, qboolean allowfail)
4724 {
4725         r_bufferdata_buffer_t *mem;
4726         int offset = 0;
4727         int padsize;
4728         float newvalue;
4729
4730         *returnbufferoffset = 0;
4731
4732         // align size to a byte boundary appropriate for the buffer type, this
4733         // makes all allocations have aligned start offsets
4734         if (type == R_BUFFERDATA_UNIFORM)
4735                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4736         else
4737                 padsize = (datasize + 15) & ~15;
4738
4739         while (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4740         {
4741                 // emergency - we ran out of space, allocate more memory
4742                 newvalue = bound(0.25f, r_bufferdatasize[type].value * 2.0f, 256.0f);
4743                 // if we're already at the limit, just fail (if allowfail is false we might run out of video ram)
4744                 if (newvalue == r_bufferdatasize[type].value && allowfail)
4745                         return NULL;
4746                 Cvar_SetValueQuick(&r_bufferdatasize[type], newvalue);
4747                 R_BufferData_Resize(type, true);
4748         }
4749
4750         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4751         offset = mem->current;
4752         mem->current += padsize;
4753
4754         // upload the data to the buffer at the chosen offset
4755         if (offset == 0)
4756                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4757         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4758
4759         // count the usage for stats
4760         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4761         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4762
4763         // return the buffer offset
4764         *returnbufferoffset = offset;
4765
4766         return mem->buffer;
4767 }
4768
4769 //==================================================================================
4770
4771 // LordHavoc: animcache originally written by Echon, rewritten since then
4772
4773 /**
4774  * Animation cache prevents re-generating mesh data for an animated model
4775  * multiple times in one frame for lighting, shadowing, reflections, etc.
4776  */
4777
4778 void R_AnimCache_Free(void)
4779 {
4780 }
4781
4782 void R_AnimCache_ClearCache(void)
4783 {
4784         int i;
4785         entity_render_t *ent;
4786
4787         for (i = 0;i < r_refdef.scene.numentities;i++)
4788         {
4789                 ent = r_refdef.scene.entities[i];
4790                 ent->animcache_vertex3f = NULL;
4791                 ent->animcache_vertex3f_vertexbuffer = NULL;
4792                 ent->animcache_vertex3f_bufferoffset = 0;
4793                 ent->animcache_normal3f = NULL;
4794                 ent->animcache_normal3f_vertexbuffer = NULL;
4795                 ent->animcache_normal3f_bufferoffset = 0;
4796                 ent->animcache_svector3f = NULL;
4797                 ent->animcache_svector3f_vertexbuffer = NULL;
4798                 ent->animcache_svector3f_bufferoffset = 0;
4799                 ent->animcache_tvector3f = NULL;
4800                 ent->animcache_tvector3f_vertexbuffer = NULL;
4801                 ent->animcache_tvector3f_bufferoffset = 0;
4802                 ent->animcache_vertexmesh = NULL;
4803                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4804                 ent->animcache_vertexmesh_bufferoffset = 0;
4805                 ent->animcache_skeletaltransform3x4 = NULL;
4806                 ent->animcache_skeletaltransform3x4buffer = NULL;
4807                 ent->animcache_skeletaltransform3x4offset = 0;
4808                 ent->animcache_skeletaltransform3x4size = 0;
4809         }
4810 }
4811
4812 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4813 {
4814         int i;
4815
4816         // check if we need the meshbuffers
4817         if (!vid.useinterleavedarrays)
4818                 return;
4819
4820         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4821                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4822         // TODO: upload vertexbuffer?
4823         if (ent->animcache_vertexmesh)
4824         {
4825                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4826                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4827                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4828                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4829                 for (i = 0;i < numvertices;i++)
4830                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4831                 if (ent->animcache_svector3f)
4832                         for (i = 0;i < numvertices;i++)
4833                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4834                 if (ent->animcache_tvector3f)
4835                         for (i = 0;i < numvertices;i++)
4836                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4837                 if (ent->animcache_normal3f)
4838                         for (i = 0;i < numvertices;i++)
4839                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4840         }
4841 }
4842
4843 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4844 {
4845         dp_model_t *model = ent->model;
4846         int numvertices;
4847
4848         // see if this ent is worth caching
4849         if (!model || !model->Draw || !model->AnimateVertices)
4850                 return false;
4851         // nothing to cache if it contains no animations and has no skeleton
4852         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4853                 return false;
4854         // see if it is already cached for gpuskeletal
4855         if (ent->animcache_skeletaltransform3x4)
4856                 return false;
4857         // see if it is already cached as a mesh
4858         if (ent->animcache_vertex3f)
4859         {
4860                 // check if we need to add normals or tangents
4861                 if (ent->animcache_normal3f)
4862                         wantnormals = false;
4863                 if (ent->animcache_svector3f)
4864                         wanttangents = false;
4865                 if (!wantnormals && !wanttangents)
4866                         return false;
4867         }
4868
4869         // check which kind of cache we need to generate
4870         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4871         {
4872                 // cache the skeleton so the vertex shader can use it
4873                 int i;
4874                 int blends;
4875                 const skeleton_t *skeleton = ent->skeleton;
4876                 const frameblend_t *frameblend = ent->frameblend;
4877                 float *boneposerelative;
4878                 float m[12];
4879                 static float bonepose[256][12];
4880                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4881                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4882                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4883                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4884                 boneposerelative = ent->animcache_skeletaltransform3x4;
4885                 if (skeleton && !skeleton->relativetransforms)
4886                         skeleton = NULL;
4887                 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4888                 if (skeleton)
4889                 {
4890                         for (i = 0;i < model->num_bones;i++)
4891                         {
4892                                 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4893                                 if (model->data_bones[i].parent >= 0)
4894                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4895                                 else
4896                                         memcpy(bonepose[i], m, sizeof(m));
4897
4898                                 // create a relative deformation matrix to describe displacement
4899                                 // from the base mesh, which is used by the actual weighting
4900                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4901                         }
4902                 }
4903                 else
4904                 {
4905                         for (i = 0;i < model->num_bones;i++)
4906                         {
4907                                 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4908                                 float lerp = frameblend[0].lerp,
4909                                         tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4910                                         rx = pose7s[3] * lerp,
4911                                         ry = pose7s[4] * lerp,
4912                                         rz = pose7s[5] * lerp,
4913                                         rw = pose7s[6] * lerp,
4914                                         dx = tx*rw + ty*rz - tz*ry,
4915                                         dy = -tx*rz + ty*rw + tz*rx,
4916                                         dz = tx*ry - ty*rx + tz*rw,
4917                                         dw = -tx*rx - ty*ry - tz*rz,
4918                                         scale, sx, sy, sz, sw;
4919                                 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4920                                 {
4921                                         const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4922                                         float lerp = frameblend[blends].lerp,
4923                                                 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4924                                                 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4925                                         if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4926                                         qx *= lerp;
4927                                         qy *= lerp;
4928                                         qz *= lerp;
4929                                         qw *= lerp;
4930                                         rx += qx;
4931                                         ry += qy;
4932                                         rz += qz;
4933                                         rw += qw;
4934                                         dx += tx*qw + ty*qz - tz*qy;
4935                                         dy += -tx*qz + ty*qw + tz*qx;
4936                                         dz += tx*qy - ty*qx + tz*qw;
4937                                         dw += -tx*qx - ty*qy - tz*qz;
4938                                 }
4939                                 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4940                                 sx = rx * scale;
4941                                 sy = ry * scale;
4942                                 sz = rz * scale;
4943                                 sw = rw * scale;
4944                                 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4945                                 m[1] = 2*(sx*ry - sw*rz);
4946                                 m[2] = 2*(sx*rz + sw*ry);
4947                                 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4948                                 m[4] = 2*(sx*ry + sw*rz);
4949                                 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4950                                 m[6] = 2*(sy*rz - sw*rx);
4951                                 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4952                                 m[8] = 2*(sx*rz - sw*ry);
4953                                 m[9] = 2*(sy*rz + sw*rx);
4954                                 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4955                                 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4956                                 if (i == r_skeletal_debugbone.integer)
4957                                         m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4958                                 m[3] *= r_skeletal_debugtranslatex.value;
4959                                 m[7] *= r_skeletal_debugtranslatey.value;
4960                                 m[11] *= r_skeletal_debugtranslatez.value;
4961                                 if (model->data_bones[i].parent >= 0)
4962                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4963                                 else
4964                                         memcpy(bonepose[i], m, sizeof(m));
4965                                 // create a relative deformation matrix to describe displacement
4966                                 // from the base mesh, which is used by the actual weighting
4967                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4968                         }
4969                 }
4970                 // note: this can fail if the buffer is at the grow limit
4971                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4972                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset, true);
4973         }
4974         else if (ent->animcache_vertex3f)
4975         {
4976                 // mesh was already cached but we may need to add normals/tangents
4977                 // (this only happens with multiple views, reflections, cameras, etc)
4978                 if (wantnormals || wanttangents)
4979                 {
4980                         numvertices = model->surfmesh.num_vertices;
4981                         if (wantnormals)
4982                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4983                         if (wanttangents)
4984                         {
4985                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4986                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4987                         }
4988                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4989                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4990                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4991                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4992                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4993                 }
4994         }
4995         else
4996         {
4997                 // generate mesh cache
4998                 numvertices = model->surfmesh.num_vertices;
4999                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5000                 if (wantnormals)
5001                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5002                 if (wanttangents)
5003                 {
5004                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5005                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5006                 }
5007                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5008                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5009                 if (wantnormals || wanttangents)
5010                 {
5011                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5012                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5013                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5014                 }
5015                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5016                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5017                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5018         }
5019         return true;
5020 }
5021
5022 void R_AnimCache_CacheVisibleEntities(void)
5023 {
5024         int i;
5025         qboolean wantnormals = true;
5026         qboolean wanttangents = !r_showsurfaces.integer;
5027
5028         switch(vid.renderpath)
5029         {
5030         case RENDERPATH_GL20:
5031         case RENDERPATH_D3D9:
5032         case RENDERPATH_D3D10:
5033         case RENDERPATH_D3D11:
5034         case RENDERPATH_GLES2:
5035                 break;
5036         case RENDERPATH_GL11:
5037         case RENDERPATH_GL13:
5038         case RENDERPATH_GLES1:
5039                 wanttangents = false;
5040                 break;
5041         case RENDERPATH_SOFT:
5042                 break;
5043         }
5044
5045         if (r_shownormals.integer)
5046                 wanttangents = wantnormals = true;
5047
5048         // TODO: thread this
5049         // NOTE: R_PrepareRTLights() also caches entities
5050
5051         for (i = 0;i < r_refdef.scene.numentities;i++)
5052                 if (r_refdef.viewcache.entityvisible[i])
5053                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5054 }
5055
5056 //==================================================================================
5057
5058 extern cvar_t r_overheadsprites_pushback;
5059
5060 static void R_View_UpdateEntityLighting (void)
5061 {
5062         int i;
5063         entity_render_t *ent;
5064         vec3_t tempdiffusenormal, avg;
5065         vec_t f, fa, fd, fdd;
5066         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5067
5068         for (i = 0;i < r_refdef.scene.numentities;i++)
5069         {
5070                 ent = r_refdef.scene.entities[i];
5071
5072                 // skip unseen models
5073                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5074                         continue;
5075
5076                 // skip bsp models
5077                 if (ent->model && ent->model == cl.worldmodel)
5078                 {
5079                         // TODO: use modellight for r_ambient settings on world?
5080                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5081                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5082                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5083                         continue;
5084                 }
5085                 
5086                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5087                 {
5088                         // aleady updated by CSQC
5089                         // TODO: force modellight on BSP models in this case?
5090                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5091                 }
5092                 else
5093                 {
5094                         // fetch the lighting from the worldmodel data
5095                         VectorClear(ent->modellight_ambient);
5096                         VectorClear(ent->modellight_diffuse);
5097                         VectorClear(tempdiffusenormal);
5098                         if (ent->flags & RENDER_LIGHT)
5099                         {
5100                                 vec3_t org;
5101                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5102
5103                                 // complete lightning for lit sprites
5104                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5105                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5106                                 {
5107                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5108                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5109                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5110                                 }
5111                                 else
5112                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5113
5114                                 if(ent->flags & RENDER_EQUALIZE)
5115                                 {
5116                                         // first fix up ambient lighting...
5117                                         if(r_equalize_entities_minambient.value > 0)
5118                                         {
5119                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5120                                                 if(fd > 0)
5121                                                 {
5122                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5123                                                         if(fa < r_equalize_entities_minambient.value * fd)
5124                                                         {
5125                                                                 // solve:
5126                                                                 //   fa'/fd' = minambient
5127                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5128                                                                 //   ...
5129                                                                 //   fa' = fd' * minambient
5130                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5131                                                                 //   ...
5132                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5133                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5134                                                                 //   ...
5135                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5136                                                                 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
5137                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5138                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5139                                                         }
5140                                                 }
5141                                         }
5142
5143                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5144                                         {
5145                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5146                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5147                                                 f = fa + 0.25 * fd;
5148                                                 if(f > 0)
5149                                                 {
5150                                                         // adjust brightness and saturation to target
5151                                                         avg[0] = avg[1] = avg[2] = fa / f;
5152                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5153                                                         avg[0] = avg[1] = avg[2] = fd / f;
5154                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5155                                                 }
5156                                         }
5157                                 }
5158                         }
5159                         else // highly rare
5160                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5161                 }
5162
5163                 // move the light direction into modelspace coordinates for lighting code
5164                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5165                 if(VectorLength2(ent->modellight_lightdir) == 0)
5166                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5167                 VectorNormalize(ent->modellight_lightdir);
5168         }
5169 }
5170
5171 #define MAX_LINEOFSIGHTTRACES 64
5172
5173 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5174 {
5175         int i;
5176         vec3_t boxmins, boxmaxs;
5177         vec3_t start;
5178         vec3_t end;
5179         dp_model_t *model = r_refdef.scene.worldmodel;
5180
5181         if (!model || !model->brush.TraceLineOfSight)
5182                 return true;
5183
5184         // expand the box a little
5185         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5186         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5187         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5188         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5189         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5190         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5191
5192         // return true if eye is inside enlarged box
5193         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5194                 return true;
5195
5196         // try center
5197         VectorCopy(eye, start);
5198         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5199         if (model->brush.TraceLineOfSight(model, start, end))
5200                 return true;
5201
5202         // try various random positions
5203         for (i = 0;i < numsamples;i++)
5204         {
5205                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5206                 if (model->brush.TraceLineOfSight(model, start, end))
5207                         return true;
5208         }
5209
5210         return false;
5211 }
5212
5213
5214 static void R_View_UpdateEntityVisible (void)
5215 {
5216         int i;
5217         int renderimask;
5218         int samples;
5219         entity_render_t *ent;
5220
5221         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5222                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5223                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5224                 :                                                          RENDER_EXTERIORMODEL;
5225         if (!r_drawviewmodel.integer)
5226                 renderimask |= RENDER_VIEWMODEL;
5227         if (!r_drawexteriormodel.integer)
5228                 renderimask |= RENDER_EXTERIORMODEL;
5229         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5230         {
5231                 // worldmodel can check visibility
5232                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
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                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
5249                 }
5250         }
5251         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5252                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5253         {
5254                 for (i = 0;i < r_refdef.scene.numentities;i++)
5255                 {
5256                         if (!r_refdef.viewcache.entityvisible[i])
5257                                 continue;
5258                         ent = r_refdef.scene.entities[i];
5259                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5260                         {
5261                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5262                                 if (samples < 0)
5263                                         continue; // temp entities do pvs only
5264                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5265                                         ent->last_trace_visibility = realtime;
5266                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5267                                         r_refdef.viewcache.entityvisible[i] = 0;
5268                         }
5269                 }
5270         }
5271 }
5272
5273 /// only used if skyrendermasked, and normally returns false
5274 static int R_DrawBrushModelsSky (void)
5275 {
5276         int i, sky;
5277         entity_render_t *ent;
5278
5279         sky = false;
5280         for (i = 0;i < r_refdef.scene.numentities;i++)
5281         {
5282                 if (!r_refdef.viewcache.entityvisible[i])
5283                         continue;
5284                 ent = r_refdef.scene.entities[i];
5285                 if (!ent->model || !ent->model->DrawSky)
5286                         continue;
5287                 ent->model->DrawSky(ent);
5288                 sky = true;
5289         }
5290         return sky;
5291 }
5292
5293 static void R_DrawNoModel(entity_render_t *ent);
5294 static void R_DrawModels(void)
5295 {
5296         int i;
5297         entity_render_t *ent;
5298
5299         for (i = 0;i < r_refdef.scene.numentities;i++)
5300         {
5301                 if (!r_refdef.viewcache.entityvisible[i])
5302                         continue;
5303                 ent = r_refdef.scene.entities[i];
5304                 r_refdef.stats[r_stat_entities]++;
5305                 /*
5306                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5307                 {
5308                         vec3_t f, l, u, o;
5309                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5310                         Con_Printf("R_DrawModels\n");
5311                         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]);
5312                         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);
5313                         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);
5314                 }
5315                 */
5316                 if (ent->model && ent->model->Draw != NULL)
5317                         ent->model->Draw(ent);
5318                 else
5319                         R_DrawNoModel(ent);
5320         }
5321 }
5322
5323 static void R_DrawModelsDepth(void)
5324 {
5325         int i;
5326         entity_render_t *ent;
5327
5328         for (i = 0;i < r_refdef.scene.numentities;i++)
5329         {
5330                 if (!r_refdef.viewcache.entityvisible[i])
5331                         continue;
5332                 ent = r_refdef.scene.entities[i];
5333                 if (ent->model && ent->model->DrawDepth != NULL)
5334                         ent->model->DrawDepth(ent);
5335         }
5336 }
5337
5338 static void R_DrawModelsDebug(void)
5339 {
5340         int i;
5341         entity_render_t *ent;
5342
5343         for (i = 0;i < r_refdef.scene.numentities;i++)
5344         {
5345                 if (!r_refdef.viewcache.entityvisible[i])
5346                         continue;
5347                 ent = r_refdef.scene.entities[i];
5348                 if (ent->model && ent->model->DrawDebug != NULL)
5349                         ent->model->DrawDebug(ent);
5350         }
5351 }
5352
5353 static void R_DrawModelsAddWaterPlanes(void)
5354 {
5355         int i;
5356         entity_render_t *ent;
5357
5358         for (i = 0;i < r_refdef.scene.numentities;i++)
5359         {
5360                 if (!r_refdef.viewcache.entityvisible[i])
5361                         continue;
5362                 ent = r_refdef.scene.entities[i];
5363                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5364                         ent->model->DrawAddWaterPlanes(ent);
5365         }
5366 }
5367
5368 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}};
5369
5370 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5371 {
5372         if (r_hdr_irisadaptation.integer)
5373         {
5374                 vec3_t p;
5375                 vec3_t ambient;
5376                 vec3_t diffuse;
5377                 vec3_t diffusenormal;
5378                 vec3_t forward;
5379                 vec_t brightness = 0.0f;
5380                 vec_t goal;
5381                 vec_t current;
5382                 vec_t d;
5383                 int c;
5384                 VectorCopy(r_refdef.view.forward, forward);
5385                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5386                 {
5387                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5388                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5389                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5390                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5391                         d = DotProduct(forward, diffusenormal);
5392                         brightness += VectorLength(ambient);
5393                         if (d > 0)
5394                                 brightness += d * VectorLength(diffuse);
5395                 }
5396                 brightness *= 1.0f / c;
5397                 brightness += 0.00001f; // make sure it's never zero
5398                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5399                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5400                 current = r_hdr_irisadaptation_value.value;
5401                 if (current < goal)
5402                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5403                 else if (current > goal)
5404                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5405                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5406                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5407         }
5408         else if (r_hdr_irisadaptation_value.value != 1.0f)
5409                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5410 }
5411
5412 static void R_View_SetFrustum(const int *scissor)
5413 {
5414         int i;
5415         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5416         vec3_t forward, left, up, origin, v;
5417
5418         if(scissor)
5419         {
5420                 // flipped x coordinates (because x points left here)
5421                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5422                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5423
5424                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5425                 switch(vid.renderpath)
5426                 {
5427                         case RENDERPATH_D3D9:
5428                         case RENDERPATH_D3D10:
5429                         case RENDERPATH_D3D11:
5430                                 // non-flipped y coordinates
5431                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5432                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5433                                 break;
5434                         case RENDERPATH_SOFT:
5435                         case RENDERPATH_GL11:
5436                         case RENDERPATH_GL13:
5437                         case RENDERPATH_GL20:
5438                         case RENDERPATH_GLES1:
5439                         case RENDERPATH_GLES2:
5440                                 // non-flipped y coordinates
5441                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5442                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5443                                 break;
5444                 }
5445         }
5446
5447         // we can't trust r_refdef.view.forward and friends in reflected scenes
5448         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5449
5450 #if 0
5451         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5452         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5453         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5454         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5455         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5456         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5457         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5458         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5459         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5460         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5461         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5462         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5463 #endif
5464
5465 #if 0
5466         zNear = r_refdef.nearclip;
5467         nudge = 1.0 - 1.0 / (1<<23);
5468         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5469         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5470         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5471         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5472         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5473         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5474         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5475         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5476 #endif
5477
5478
5479
5480 #if 0
5481         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5482         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5483         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5484         r_refdef.view.frustum[0].dist = m[15] - m[12];
5485
5486         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5487         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5488         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5489         r_refdef.view.frustum[1].dist = m[15] + m[12];
5490
5491         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5492         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5493         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5494         r_refdef.view.frustum[2].dist = m[15] - m[13];
5495
5496         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5497         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5498         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5499         r_refdef.view.frustum[3].dist = m[15] + m[13];
5500
5501         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5502         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5503         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5504         r_refdef.view.frustum[4].dist = m[15] - m[14];
5505
5506         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5507         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5508         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5509         r_refdef.view.frustum[5].dist = m[15] + m[14];
5510 #endif
5511
5512         if (r_refdef.view.useperspective)
5513         {
5514                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5515                 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]);
5516                 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]);
5517                 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]);
5518                 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]);
5519
5520                 // then the normals from the corners relative to origin
5521                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5522                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5523                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5524                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5525
5526                 // in a NORMAL view, forward cross left == up
5527                 // in a REFLECTED view, forward cross left == down
5528                 // so our cross products above need to be adjusted for a left handed coordinate system
5529                 CrossProduct(forward, left, v);
5530                 if(DotProduct(v, up) < 0)
5531                 {
5532                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5533                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5534                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5535                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5536                 }
5537
5538                 // Leaving those out was a mistake, those were in the old code, and they
5539                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5540                 // I couldn't reproduce it after adding those normalizations. --blub
5541                 VectorNormalize(r_refdef.view.frustum[0].normal);
5542                 VectorNormalize(r_refdef.view.frustum[1].normal);
5543                 VectorNormalize(r_refdef.view.frustum[2].normal);
5544                 VectorNormalize(r_refdef.view.frustum[3].normal);
5545
5546                 // make the corners absolute
5547                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5548                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5549                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5550                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5551
5552                 // one more normal
5553                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5554
5555                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5556                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5557                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5558                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5559                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5560         }
5561         else
5562         {
5563                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5564                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5565                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5566                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5567                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5568                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5569                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5570                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5571                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5572                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5573         }
5574         r_refdef.view.numfrustumplanes = 5;
5575
5576         if (r_refdef.view.useclipplane)
5577         {
5578                 r_refdef.view.numfrustumplanes = 6;
5579                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5580         }
5581
5582         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5583                 PlaneClassify(r_refdef.view.frustum + i);
5584
5585         // LordHavoc: note to all quake engine coders, Quake had a special case
5586         // for 90 degrees which assumed a square view (wrong), so I removed it,
5587         // Quake2 has it disabled as well.
5588
5589         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5590         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5591         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5592         //PlaneClassify(&frustum[0]);
5593
5594         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5595         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5596         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5597         //PlaneClassify(&frustum[1]);
5598
5599         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5600         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5601         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5602         //PlaneClassify(&frustum[2]);
5603
5604         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5605         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5606         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5607         //PlaneClassify(&frustum[3]);
5608
5609         // nearclip plane
5610         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5611         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5612         //PlaneClassify(&frustum[4]);
5613 }
5614
5615 static void R_View_UpdateWithScissor(const int *myscissor)
5616 {
5617         R_Main_ResizeViewCache();
5618         R_View_SetFrustum(myscissor);
5619         R_View_WorldVisibility(r_refdef.view.useclipplane);
5620         R_View_UpdateEntityVisible();
5621         R_View_UpdateEntityLighting();
5622 }
5623
5624 static void R_View_Update(void)
5625 {
5626         R_Main_ResizeViewCache();
5627         R_View_SetFrustum(NULL);
5628         R_View_WorldVisibility(r_refdef.view.useclipplane);
5629         R_View_UpdateEntityVisible();
5630         R_View_UpdateEntityLighting();
5631 }
5632
5633 float viewscalefpsadjusted = 1.0f;
5634
5635 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5636 {
5637         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5638         scale = bound(0.03125f, scale, 1.0f);
5639         *outwidth = (int)ceil(width * scale);
5640         *outheight = (int)ceil(height * scale);
5641 }
5642
5643 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5644 {
5645         const float *customclipplane = NULL;
5646         float plane[4];
5647         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5648         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5649         {
5650                 // LordHavoc: couldn't figure out how to make this approach the
5651                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5652                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5653                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5654                         dist = r_refdef.view.clipplane.dist;
5655                 plane[0] = r_refdef.view.clipplane.normal[0];
5656                 plane[1] = r_refdef.view.clipplane.normal[1];
5657                 plane[2] = r_refdef.view.clipplane.normal[2];
5658                 plane[3] = -dist;
5659                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5660         }
5661
5662         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5663         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5664
5665         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5666         if (!r_refdef.view.useperspective)
5667                 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);
5668         else if (vid.stencil && r_useinfinitefarclip.integer)
5669                 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);
5670         else
5671                 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);
5672         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5673         R_SetViewport(&r_refdef.view.viewport);
5674         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5675         {
5676                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5677                 float screenplane[4];
5678                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5679                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5680                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5681                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5682                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5683         }
5684 }
5685
5686 void R_EntityMatrix(const matrix4x4_t *matrix)
5687 {
5688         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5689         {
5690                 gl_modelmatrixchanged = false;
5691                 gl_modelmatrix = *matrix;
5692                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5693                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5694                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5695                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5696                 CHECKGLERROR
5697                 switch(vid.renderpath)
5698                 {
5699                 case RENDERPATH_D3D9:
5700 #ifdef SUPPORTD3D
5701                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5702                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5703 #endif
5704                         break;
5705                 case RENDERPATH_D3D10:
5706                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5707                         break;
5708                 case RENDERPATH_D3D11:
5709                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5710                         break;
5711                 case RENDERPATH_GL11:
5712                 case RENDERPATH_GL13:
5713                 case RENDERPATH_GLES1:
5714                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5715                         break;
5716                 case RENDERPATH_SOFT:
5717                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5718                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5719                         break;
5720                 case RENDERPATH_GL20:
5721                 case RENDERPATH_GLES2:
5722                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5723                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5724                         break;
5725                 }
5726         }
5727 }
5728
5729 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5730 {
5731         r_viewport_t viewport;
5732
5733         CHECKGLERROR
5734
5735         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5736         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);
5737         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5738         R_SetViewport(&viewport);
5739         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5740         GL_Color(1, 1, 1, 1);
5741         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5742         GL_BlendFunc(GL_ONE, GL_ZERO);
5743         GL_ScissorTest(false);
5744         GL_DepthMask(false);
5745         GL_DepthRange(0, 1);
5746         GL_DepthTest(false);
5747         GL_DepthFunc(GL_LEQUAL);
5748         R_EntityMatrix(&identitymatrix);
5749         R_Mesh_ResetTextureState();
5750         GL_PolygonOffset(0, 0);
5751         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5752         switch(vid.renderpath)
5753         {
5754         case RENDERPATH_GL11:
5755         case RENDERPATH_GL13:
5756         case RENDERPATH_GL20:
5757         case RENDERPATH_GLES1:
5758         case RENDERPATH_GLES2:
5759                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5760                 break;
5761         case RENDERPATH_D3D9:
5762         case RENDERPATH_D3D10:
5763         case RENDERPATH_D3D11:
5764         case RENDERPATH_SOFT:
5765                 break;
5766         }
5767         GL_CullFace(GL_NONE);
5768
5769         CHECKGLERROR
5770 }
5771
5772 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5773 {
5774         DrawQ_Finish();
5775
5776         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5777 }
5778
5779 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5780 {
5781         DrawQ_Finish();
5782
5783         R_SetupView(true, fbo, depthtexture, colortexture);
5784         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5785         GL_Color(1, 1, 1, 1);
5786         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5787         GL_BlendFunc(GL_ONE, GL_ZERO);
5788         GL_ScissorTest(true);
5789         GL_DepthMask(true);
5790         GL_DepthRange(0, 1);
5791         GL_DepthTest(true);
5792         GL_DepthFunc(GL_LEQUAL);
5793         R_EntityMatrix(&identitymatrix);
5794         R_Mesh_ResetTextureState();
5795         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5796         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5797         switch(vid.renderpath)
5798         {
5799         case RENDERPATH_GL11:
5800         case RENDERPATH_GL13:
5801         case RENDERPATH_GL20:
5802         case RENDERPATH_GLES1:
5803         case RENDERPATH_GLES2:
5804                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5805                 break;
5806         case RENDERPATH_D3D9:
5807         case RENDERPATH_D3D10:
5808         case RENDERPATH_D3D11:
5809         case RENDERPATH_SOFT:
5810                 break;
5811         }
5812         GL_CullFace(r_refdef.view.cullface_back);
5813 }
5814
5815 /*
5816 ================
5817 R_RenderView_UpdateViewVectors
5818 ================
5819 */
5820 void R_RenderView_UpdateViewVectors(void)
5821 {
5822         // break apart the view matrix into vectors for various purposes
5823         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5824         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5825         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5826         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5827         // make an inverted copy of the view matrix for tracking sprites
5828         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5829 }
5830
5831 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5832 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5833
5834 static void R_Water_StartFrame(void)
5835 {
5836         int i;
5837         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5838         r_waterstate_waterplane_t *p;
5839         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;
5840
5841         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5842                 return;
5843
5844         switch(vid.renderpath)
5845         {
5846         case RENDERPATH_GL20:
5847         case RENDERPATH_D3D9:
5848         case RENDERPATH_D3D10:
5849         case RENDERPATH_D3D11:
5850         case RENDERPATH_SOFT:
5851         case RENDERPATH_GLES2:
5852                 break;
5853         case RENDERPATH_GL11:
5854         case RENDERPATH_GL13:
5855         case RENDERPATH_GLES1:
5856                 return;
5857         }
5858
5859         // set waterwidth and waterheight to the water resolution that will be
5860         // used (often less than the screen resolution for faster rendering)
5861         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5862
5863         // calculate desired texture sizes
5864         // can't use water if the card does not support the texture size
5865         if (!r_water.integer || r_showsurfaces.integer)
5866                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5867         else if (vid.support.arb_texture_non_power_of_two)
5868         {
5869                 texturewidth = waterwidth;
5870                 textureheight = waterheight;
5871                 camerawidth = waterwidth;
5872                 cameraheight = waterheight;
5873         }
5874         else
5875         {
5876                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5877                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5878                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5879                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5880         }
5881
5882         // allocate textures as needed
5883         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))
5884         {
5885                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5886                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5887                 {
5888                         if (p->texture_refraction)
5889                                 R_FreeTexture(p->texture_refraction);
5890                         p->texture_refraction = NULL;
5891                         if (p->fbo_refraction)
5892                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5893                         p->fbo_refraction = 0;
5894                         if (p->texture_reflection)
5895                                 R_FreeTexture(p->texture_reflection);
5896                         p->texture_reflection = NULL;
5897                         if (p->fbo_reflection)
5898                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5899                         p->fbo_reflection = 0;
5900                         if (p->texture_camera)
5901                                 R_FreeTexture(p->texture_camera);
5902                         p->texture_camera = NULL;
5903                         if (p->fbo_camera)
5904                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5905                         p->fbo_camera = 0;
5906                 }
5907                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5908                 r_fb.water.texturewidth = texturewidth;
5909                 r_fb.water.textureheight = textureheight;
5910                 r_fb.water.camerawidth = camerawidth;
5911                 r_fb.water.cameraheight = cameraheight;
5912         }
5913
5914         if (r_fb.water.texturewidth)
5915         {
5916                 int scaledwidth, scaledheight;
5917
5918                 r_fb.water.enabled = true;
5919
5920                 // water resolution is usually reduced
5921                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5922                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5923                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5924
5925                 // set up variables that will be used in shader setup
5926                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5927                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5928                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5929                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5930         }
5931
5932         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5933         r_fb.water.numwaterplanes = 0;
5934 }
5935
5936 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5937 {
5938         int planeindex, bestplaneindex, vertexindex;
5939         vec3_t mins, maxs, normal, center, v, n;
5940         vec_t planescore, bestplanescore;
5941         mplane_t plane;
5942         r_waterstate_waterplane_t *p;
5943         texture_t *t = R_GetCurrentTexture(surface->texture);
5944
5945         rsurface.texture = t;
5946         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5947         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5948         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5949                 return;
5950         // average the vertex normals, find the surface bounds (after deformvertexes)
5951         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5952         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5953         VectorCopy(n, normal);
5954         VectorCopy(v, mins);
5955         VectorCopy(v, maxs);
5956         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5957         {
5958                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5959                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5960                 VectorAdd(normal, n, normal);
5961                 mins[0] = min(mins[0], v[0]);
5962                 mins[1] = min(mins[1], v[1]);
5963                 mins[2] = min(mins[2], v[2]);
5964                 maxs[0] = max(maxs[0], v[0]);
5965                 maxs[1] = max(maxs[1], v[1]);
5966                 maxs[2] = max(maxs[2], v[2]);
5967         }
5968         VectorNormalize(normal);
5969         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5970
5971         VectorCopy(normal, plane.normal);
5972         VectorNormalize(plane.normal);
5973         plane.dist = DotProduct(center, plane.normal);
5974         PlaneClassify(&plane);
5975         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5976         {
5977                 // skip backfaces (except if nocullface is set)
5978 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5979 //                      return;
5980                 VectorNegate(plane.normal, plane.normal);
5981                 plane.dist *= -1;
5982                 PlaneClassify(&plane);
5983         }
5984
5985
5986         // find a matching plane if there is one
5987         bestplaneindex = -1;
5988         bestplanescore = 1048576.0f;
5989         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5990         {
5991                 if(p->camera_entity == t->camera_entity)
5992                 {
5993                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5994                         if (bestplaneindex < 0 || bestplanescore > planescore)
5995                         {
5996                                 bestplaneindex = planeindex;
5997                                 bestplanescore = planescore;
5998                         }
5999                 }
6000         }
6001         planeindex = bestplaneindex;
6002         p = r_fb.water.waterplanes + planeindex;
6003
6004         // if this surface does not fit any known plane rendered this frame, add one
6005         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6006         {
6007                 // store the new plane
6008                 planeindex = r_fb.water.numwaterplanes++;
6009                 p = r_fb.water.waterplanes + planeindex;
6010                 p->plane = plane;
6011                 // clear materialflags and pvs
6012                 p->materialflags = 0;
6013                 p->pvsvalid = false;
6014                 p->camera_entity = t->camera_entity;
6015                 VectorCopy(mins, p->mins);
6016                 VectorCopy(maxs, p->maxs);
6017         }
6018         else
6019         {
6020                 // merge mins/maxs when we're adding this surface to the plane
6021                 p->mins[0] = min(p->mins[0], mins[0]);
6022                 p->mins[1] = min(p->mins[1], mins[1]);
6023                 p->mins[2] = min(p->mins[2], mins[2]);
6024                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6025                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6026                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6027         }
6028         // merge this surface's materialflags into the waterplane
6029         p->materialflags |= t->currentmaterialflags;
6030         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6031         {
6032                 // merge this surface's PVS into the waterplane
6033                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6034                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6035                 {
6036                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6037                         p->pvsvalid = true;
6038                 }
6039         }
6040 }
6041
6042 extern cvar_t r_drawparticles;
6043 extern cvar_t r_drawdecals;
6044
6045 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6046 {
6047         int myscissor[4];
6048         r_refdef_view_t originalview;
6049         r_refdef_view_t myview;
6050         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;
6051         r_waterstate_waterplane_t *p;
6052         vec3_t visorigin;
6053         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;
6054         char vabuf[1024];
6055
6056         originalview = r_refdef.view;
6057
6058         // lowquality hack, temporarily shut down some cvars and restore afterwards
6059         qualityreduction = r_water_lowquality.integer;
6060         if (qualityreduction > 0)
6061         {
6062                 if (qualityreduction >= 1)
6063                 {
6064                         old_r_shadows = r_shadows.integer;
6065                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6066                         old_r_dlight = r_shadow_realtime_dlight.integer;
6067                         Cvar_SetValueQuick(&r_shadows, 0);
6068                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6069                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6070                 }
6071                 if (qualityreduction >= 2)
6072                 {
6073                         old_r_dynamic = r_dynamic.integer;
6074                         old_r_particles = r_drawparticles.integer;
6075                         old_r_decals = r_drawdecals.integer;
6076                         Cvar_SetValueQuick(&r_dynamic, 0);
6077                         Cvar_SetValueQuick(&r_drawparticles, 0);
6078                         Cvar_SetValueQuick(&r_drawdecals, 0);
6079                 }
6080         }
6081
6082         // make sure enough textures are allocated
6083         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6084         {
6085                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6086                 {
6087                         if (!p->texture_refraction)
6088                                 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);
6089                         if (!p->texture_refraction)
6090                                 goto error;
6091                         if (usewaterfbo)
6092                         {
6093                                 if (r_fb.water.depthtexture == NULL)
6094                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6095                                 if (p->fbo_refraction == 0)
6096                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6097                         }
6098                 }
6099                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6100                 {
6101                         if (!p->texture_camera)
6102                                 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);
6103                         if (!p->texture_camera)
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_camera == 0)
6110                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6111                         }
6112                 }
6113
6114                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6115                 {
6116                         if (!p->texture_reflection)
6117                                 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);
6118                         if (!p->texture_reflection)
6119                                 goto error;
6120                         if (usewaterfbo)
6121                         {
6122                                 if (r_fb.water.depthtexture == NULL)
6123                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6124                                 if (p->fbo_reflection == 0)
6125                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6126                         }
6127                 }
6128         }
6129
6130         // render views
6131         r_refdef.view = originalview;
6132         r_refdef.view.showdebug = false;
6133         r_refdef.view.width = r_fb.water.waterwidth;
6134         r_refdef.view.height = r_fb.water.waterheight;
6135         r_refdef.view.useclipplane = true;
6136         myview = r_refdef.view;
6137         r_fb.water.renderingscene = true;
6138         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6139         {
6140                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6141                 {
6142                         r_refdef.view = myview;
6143                         if(r_water_scissormode.integer)
6144                         {
6145                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6146                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6147                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6148                         }
6149
6150                         // render reflected scene and copy into texture
6151                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6152                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6153                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6154                         r_refdef.view.clipplane = p->plane;
6155                         // reverse the cullface settings for this render
6156                         r_refdef.view.cullface_front = GL_FRONT;
6157                         r_refdef.view.cullface_back = GL_BACK;
6158                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6159                         {
6160                                 r_refdef.view.usecustompvs = true;
6161                                 if (p->pvsvalid)
6162                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6163                                 else
6164                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6165                         }
6166
6167                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6168                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6169                         R_ClearScreen(r_refdef.fogenabled);
6170                         if(r_water_scissormode.integer & 2)
6171                                 R_View_UpdateWithScissor(myscissor);
6172                         else
6173                                 R_View_Update();
6174                         R_AnimCache_CacheVisibleEntities();
6175                         if(r_water_scissormode.integer & 1)
6176                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6177                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6178
6179                         if (!p->fbo_reflection)
6180                                 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);
6181                         r_fb.water.hideplayer = false;
6182                 }
6183
6184                 // render the normal view scene and copy into texture
6185                 // (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)
6186                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6187                 {
6188                         r_refdef.view = myview;
6189                         if(r_water_scissormode.integer)
6190                         {
6191                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6192                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6193                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6194                         }
6195
6196                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6197
6198                         r_refdef.view.clipplane = p->plane;
6199                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6200                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6201
6202                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6203                         {
6204                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6205                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6206                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6207                                 R_RenderView_UpdateViewVectors();
6208                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6209                                 {
6210                                         r_refdef.view.usecustompvs = true;
6211                                         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);
6212                                 }
6213                         }
6214
6215                         PlaneClassify(&r_refdef.view.clipplane);
6216
6217                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6218                         R_ClearScreen(r_refdef.fogenabled);
6219                         if(r_water_scissormode.integer & 2)
6220                                 R_View_UpdateWithScissor(myscissor);
6221                         else
6222                                 R_View_Update();
6223                         R_AnimCache_CacheVisibleEntities();
6224                         if(r_water_scissormode.integer & 1)
6225                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6226                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6227
6228                         if (!p->fbo_refraction)
6229                                 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);
6230                         r_fb.water.hideplayer = false;
6231                 }
6232                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6233                 {
6234                         r_refdef.view = myview;
6235
6236                         r_refdef.view.clipplane = p->plane;
6237                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6238                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6239
6240                         r_refdef.view.width = r_fb.water.camerawidth;
6241                         r_refdef.view.height = r_fb.water.cameraheight;
6242                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6243                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6244                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6245                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6246
6247                         if(p->camera_entity)
6248                         {
6249                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6250                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6251                         }
6252
6253                         // note: all of the view is used for displaying... so
6254                         // there is no use in scissoring
6255
6256                         // reverse the cullface settings for this render
6257                         r_refdef.view.cullface_front = GL_FRONT;
6258                         r_refdef.view.cullface_back = GL_BACK;
6259                         // also reverse the view matrix
6260                         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
6261                         R_RenderView_UpdateViewVectors();
6262                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6263                         {
6264                                 r_refdef.view.usecustompvs = true;
6265                                 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);
6266                         }
6267                         
6268                         // camera needs no clipplane
6269                         r_refdef.view.useclipplane = false;
6270
6271                         PlaneClassify(&r_refdef.view.clipplane);
6272
6273                         r_fb.water.hideplayer = false;
6274
6275                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6276                         R_ClearScreen(r_refdef.fogenabled);
6277                         R_View_Update();
6278                         R_AnimCache_CacheVisibleEntities();
6279                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6280
6281                         if (!p->fbo_camera)
6282                                 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);
6283                         r_fb.water.hideplayer = false;
6284                 }
6285
6286         }
6287         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6288         r_fb.water.renderingscene = false;
6289         r_refdef.view = originalview;
6290         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6291         if (!r_fb.water.depthtexture)
6292                 R_ClearScreen(r_refdef.fogenabled);
6293         R_View_Update();
6294         R_AnimCache_CacheVisibleEntities();
6295         goto finish;
6296 error:
6297         r_refdef.view = originalview;
6298         r_fb.water.renderingscene = false;
6299         Cvar_SetValueQuick(&r_water, 0);
6300         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6301 finish:
6302         // lowquality hack, restore cvars
6303         if (qualityreduction > 0)
6304         {
6305                 if (qualityreduction >= 1)
6306                 {
6307                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6308                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6309                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6310                 }
6311                 if (qualityreduction >= 2)
6312                 {
6313                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6314                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6315                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6316                 }
6317         }
6318 }
6319
6320 static void R_Bloom_StartFrame(void)
6321 {
6322         int i;
6323         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6324         int viewwidth, viewheight;
6325         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6326         textype_t textype = TEXTYPE_COLORBUFFER;
6327
6328         switch (vid.renderpath)
6329         {
6330         case RENDERPATH_GL20:
6331                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6332                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6333                 {
6334                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6335                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6336                 }
6337                 break;
6338         case RENDERPATH_GL11:
6339         case RENDERPATH_GL13:
6340         case RENDERPATH_GLES1:
6341         case RENDERPATH_GLES2:
6342         case RENDERPATH_D3D9:
6343         case RENDERPATH_D3D10:
6344         case RENDERPATH_D3D11:
6345                 r_fb.usedepthtextures = false;
6346                 break;
6347         case RENDERPATH_SOFT:
6348                 r_fb.usedepthtextures = true;
6349                 break;
6350         }
6351
6352         if (r_viewscale_fpsscaling.integer)
6353         {
6354                 double actualframetime;
6355                 double targetframetime;
6356                 double adjust;
6357                 actualframetime = r_refdef.lastdrawscreentime;
6358                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6359                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6360                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6361                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6362                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6363                 viewscalefpsadjusted += adjust;
6364                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6365         }
6366         else
6367                 viewscalefpsadjusted = 1.0f;
6368
6369         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6370
6371         switch(vid.renderpath)
6372         {
6373         case RENDERPATH_GL20:
6374         case RENDERPATH_D3D9:
6375         case RENDERPATH_D3D10:
6376         case RENDERPATH_D3D11:
6377         case RENDERPATH_SOFT:
6378         case RENDERPATH_GLES2:
6379                 break;
6380         case RENDERPATH_GL11:
6381         case RENDERPATH_GL13:
6382         case RENDERPATH_GLES1:
6383                 return;
6384         }
6385
6386         // set bloomwidth and bloomheight to the bloom resolution that will be
6387         // used (often less than the screen resolution for faster rendering)
6388         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6389         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6390         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6391         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6392         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6393
6394         // calculate desired texture sizes
6395         if (vid.support.arb_texture_non_power_of_two)
6396         {
6397                 screentexturewidth = vid.width;
6398                 screentextureheight = vid.height;
6399                 bloomtexturewidth = r_fb.bloomwidth;
6400                 bloomtextureheight = r_fb.bloomheight;
6401         }
6402         else
6403         {
6404                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6405                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6406                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6407                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6408         }
6409
6410         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))
6411         {
6412                 Cvar_SetValueQuick(&r_bloom, 0);
6413                 Cvar_SetValueQuick(&r_motionblur, 0);
6414                 Cvar_SetValueQuick(&r_damageblur, 0);
6415         }
6416
6417         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6418          && !r_bloom.integer
6419          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6420          && !useviewfbo
6421          && r_viewscale.value == 1.0f
6422          && !r_viewscale_fpsscaling.integer)
6423                 screentexturewidth = screentextureheight = 0;
6424         if (!r_bloom.integer)
6425                 bloomtexturewidth = bloomtextureheight = 0;
6426
6427         // allocate textures as needed
6428         if (r_fb.screentexturewidth != screentexturewidth
6429          || r_fb.screentextureheight != screentextureheight
6430          || r_fb.bloomtexturewidth != bloomtexturewidth
6431          || r_fb.bloomtextureheight != bloomtextureheight
6432          || r_fb.textype != textype
6433          || useviewfbo != (r_fb.fbo != 0))
6434         {
6435                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6436                 {
6437                         if (r_fb.bloomtexture[i])
6438                                 R_FreeTexture(r_fb.bloomtexture[i]);
6439                         r_fb.bloomtexture[i] = NULL;
6440
6441                         if (r_fb.bloomfbo[i])
6442                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6443                         r_fb.bloomfbo[i] = 0;
6444                 }
6445
6446                 if (r_fb.fbo)
6447                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6448                 r_fb.fbo = 0;
6449
6450                 if (r_fb.colortexture)
6451                         R_FreeTexture(r_fb.colortexture);
6452                 r_fb.colortexture = NULL;
6453
6454                 if (r_fb.depthtexture)
6455                         R_FreeTexture(r_fb.depthtexture);
6456                 r_fb.depthtexture = NULL;
6457
6458                 if (r_fb.ghosttexture)
6459                         R_FreeTexture(r_fb.ghosttexture);
6460                 r_fb.ghosttexture = NULL;
6461
6462                 r_fb.screentexturewidth = screentexturewidth;
6463                 r_fb.screentextureheight = screentextureheight;
6464                 r_fb.bloomtexturewidth = bloomtexturewidth;
6465                 r_fb.bloomtextureheight = bloomtextureheight;
6466                 r_fb.textype = textype;
6467
6468                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6469                 {
6470                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6471                                 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);
6472                         r_fb.ghosttexture_valid = false;
6473                         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);
6474                         if (useviewfbo)
6475                         {
6476                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6477                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6478                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6479                         }
6480                 }
6481
6482                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6483                 {
6484                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6485                         {
6486                                 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);
6487                                 if (useviewfbo)
6488                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6489                         }
6490                 }
6491         }
6492
6493         // bloom texture is a different resolution
6494         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6495         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6496         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6497         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6498         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6499
6500         // set up a texcoord array for the full resolution screen image
6501         // (we have to keep this around to copy back during final render)
6502         r_fb.screentexcoord2f[0] = 0;
6503         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6504         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6505         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6506         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6507         r_fb.screentexcoord2f[5] = 0;
6508         r_fb.screentexcoord2f[6] = 0;
6509         r_fb.screentexcoord2f[7] = 0;
6510
6511         if(r_fb.fbo) 
6512         {
6513                 for (i = 1;i < 8;i += 2)
6514                 {
6515                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6516                 }
6517         }
6518
6519         // set up a texcoord array for the reduced resolution bloom image
6520         // (which will be additive blended over the screen image)
6521         r_fb.bloomtexcoord2f[0] = 0;
6522         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6523         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6524         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6525         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6526         r_fb.bloomtexcoord2f[5] = 0;
6527         r_fb.bloomtexcoord2f[6] = 0;
6528         r_fb.bloomtexcoord2f[7] = 0;
6529
6530         switch(vid.renderpath)
6531         {
6532         case RENDERPATH_GL11:
6533         case RENDERPATH_GL13:
6534         case RENDERPATH_GL20:
6535         case RENDERPATH_SOFT:
6536         case RENDERPATH_GLES1:
6537         case RENDERPATH_GLES2:
6538                 break;
6539         case RENDERPATH_D3D9:
6540         case RENDERPATH_D3D10:
6541         case RENDERPATH_D3D11:
6542                 for (i = 0;i < 4;i++)
6543                 {
6544                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6545                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6546                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6547                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6548                 }
6549                 break;
6550         }
6551
6552         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6553
6554         if (r_fb.fbo)
6555                 r_refdef.view.clear = true;
6556 }
6557
6558 static void R_Bloom_MakeTexture(void)
6559 {
6560         int x, range, dir;
6561         float xoffset, yoffset, r, brighten;
6562         rtexture_t *intex;
6563         float colorscale = r_bloom_colorscale.value;
6564
6565         r_refdef.stats[r_stat_bloom]++;
6566     
6567 #if 0
6568     // this copy is unnecessary since it happens in R_BlendView already
6569         if (!r_fb.fbo)
6570         {
6571                 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);
6572                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6573         }
6574 #endif
6575
6576         // scale down screen texture to the bloom texture size
6577         CHECKGLERROR
6578         r_fb.bloomindex = 0;
6579         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6580         R_SetViewport(&r_fb.bloomviewport);
6581         GL_DepthTest(false);
6582         GL_BlendFunc(GL_ONE, GL_ZERO);
6583         GL_Color(colorscale, colorscale, colorscale, 1);
6584         // 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...
6585         switch(vid.renderpath)
6586         {
6587         case RENDERPATH_GL11:
6588         case RENDERPATH_GL13:
6589         case RENDERPATH_GL20:
6590         case RENDERPATH_GLES1:
6591         case RENDERPATH_GLES2:
6592         case RENDERPATH_SOFT:
6593                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6594                 break;
6595         case RENDERPATH_D3D9:
6596         case RENDERPATH_D3D10:
6597         case RENDERPATH_D3D11:
6598                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6599                 break;
6600         }
6601         // TODO: do boxfilter scale-down in shader?
6602         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6603         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6604         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6605
6606         // we now have a properly scaled bloom image
6607         if (!r_fb.bloomfbo[r_fb.bloomindex])
6608         {
6609                 // copy it into the bloom texture
6610                 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);
6611                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6612         }
6613
6614         // multiply bloom image by itself as many times as desired
6615         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6616         {
6617                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6618                 r_fb.bloomindex ^= 1;
6619                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6620                 x *= 2;
6621                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6622                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6623                 {
6624                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6625                         GL_Color(r,r,r,1); // apply fix factor
6626                 }
6627                 else
6628                 {
6629                         if(x <= 2)
6630                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6631                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6632                         GL_Color(1,1,1,1); // no fix factor supported here
6633                 }
6634                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6635                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6636                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6637                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6638
6639                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6640                 {
6641                         // copy the darkened image to a texture
6642                         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);
6643                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6644                 }
6645         }
6646
6647         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6648         brighten = r_bloom_brighten.value;
6649         brighten = sqrt(brighten);
6650         if(range >= 1)
6651                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6652
6653         for (dir = 0;dir < 2;dir++)
6654         {
6655                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6656                 r_fb.bloomindex ^= 1;
6657                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6658                 // blend on at multiple vertical offsets to achieve a vertical blur
6659                 // TODO: do offset blends using GLSL
6660                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6661                 GL_BlendFunc(GL_ONE, GL_ZERO);
6662                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6663                 for (x = -range;x <= range;x++)
6664                 {
6665                         if (!dir){xoffset = 0;yoffset = x;}
6666                         else {xoffset = x;yoffset = 0;}
6667                         xoffset /= (float)r_fb.bloomtexturewidth;
6668                         yoffset /= (float)r_fb.bloomtextureheight;
6669                         // compute a texcoord array with the specified x and y offset
6670                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6671                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6672                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6673                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6674                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6675                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6676                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6677                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6678                         // this r value looks like a 'dot' particle, fading sharply to
6679                         // black at the edges
6680                         // (probably not realistic but looks good enough)
6681                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6682                         //r = brighten/(range*2+1);
6683                         r = brighten / (range * 2 + 1);
6684                         if(range >= 1)
6685                                 r *= (1 - x*x/(float)(range*range));
6686                         GL_Color(r, r, r, 1);
6687                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6688                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6689                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6690                         GL_BlendFunc(GL_ONE, GL_ONE);
6691                 }
6692
6693                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6694                 {
6695                         // copy the vertically or horizontally blurred bloom view to a texture
6696                         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);
6697                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6698                 }
6699         }
6700 }
6701
6702 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6703 {
6704         unsigned int permutation;
6705         float uservecs[4][4];
6706
6707         R_EntityMatrix(&identitymatrix);
6708
6709         switch (vid.renderpath)
6710         {
6711         case RENDERPATH_GL20:
6712         case RENDERPATH_D3D9:
6713         case RENDERPATH_D3D10:
6714         case RENDERPATH_D3D11:
6715         case RENDERPATH_SOFT:
6716         case RENDERPATH_GLES2:
6717                 permutation =
6718                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6719                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6720                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6721                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6722                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6723
6724                 if (r_fb.colortexture)
6725                 {
6726                         if (!r_fb.fbo)
6727                         {
6728                                 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);
6729                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6730                         }
6731
6732                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6733                         {
6734                                 // declare variables
6735                                 float blur_factor, blur_mouseaccel, blur_velocity;
6736                                 static float blur_average; 
6737                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6738
6739                                 // set a goal for the factoring
6740                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6741                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6742                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6743                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6744                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6745                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6746
6747                                 // from the goal, pick an averaged value between goal and last value
6748                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6749                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6750
6751                                 // enforce minimum amount of blur 
6752                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6753
6754                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6755
6756                                 // calculate values into a standard alpha
6757                                 cl.motionbluralpha = 1 - exp(-
6758                                                 (
6759                                                  (r_motionblur.value * blur_factor / 80)
6760                                                  +
6761                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6762                                                 )
6763                                                 /
6764                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6765                                           );
6766
6767                                 // randomization for the blur value to combat persistent ghosting
6768                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6769                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6770
6771                                 // apply the blur
6772                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6773                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6774                                 {
6775                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6776                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6777                                         switch(vid.renderpath)
6778                                         {
6779                                         case RENDERPATH_GL11:
6780                                         case RENDERPATH_GL13:
6781                                         case RENDERPATH_GL20:
6782                                         case RENDERPATH_GLES1:
6783                                         case RENDERPATH_GLES2:
6784                                         case RENDERPATH_SOFT:
6785                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6786                                                 break;
6787                                         case RENDERPATH_D3D9:
6788                                         case RENDERPATH_D3D10:
6789                                         case RENDERPATH_D3D11:
6790                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6791                                                 break;
6792                                         }
6793                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6794                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6795                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6796                                 }
6797
6798                                 // updates old view angles for next pass
6799                                 VectorCopy(cl.viewangles, blur_oldangles);
6800
6801                                 // copy view into the ghost texture
6802                                 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);
6803                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6804                                 r_fb.ghosttexture_valid = true;
6805                         }
6806                 }
6807                 else
6808                 {
6809                         // no r_fb.colortexture means we're rendering to the real fb
6810                         // we may still have to do view tint...
6811                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6812                         {
6813                                 // apply a color tint to the whole view
6814                                 R_ResetViewRendering2D(0, NULL, NULL);
6815                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6816                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6817                                 R_SetupShader_Generic_NoTexture(false, true);
6818                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6819                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6820                         }
6821                         break; // no screen processing, no bloom, skip it
6822                 }
6823
6824                 if (r_fb.bloomtexture[0])
6825                 {
6826                         // make the bloom texture
6827                         R_Bloom_MakeTexture();
6828                 }
6829
6830 #if _MSC_VER >= 1400
6831 #define sscanf sscanf_s
6832 #endif
6833                 memset(uservecs, 0, sizeof(uservecs));
6834                 if (r_glsl_postprocess_uservec1_enable.integer)
6835                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6836                 if (r_glsl_postprocess_uservec2_enable.integer)
6837                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6838                 if (r_glsl_postprocess_uservec3_enable.integer)
6839                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6840                 if (r_glsl_postprocess_uservec4_enable.integer)
6841                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6842
6843                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6844                 GL_Color(1, 1, 1, 1);
6845                 GL_BlendFunc(GL_ONE, GL_ZERO);
6846
6847                 switch(vid.renderpath)
6848                 {
6849                 case RENDERPATH_GL20:
6850                 case RENDERPATH_GLES2:
6851                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6852                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6853                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6854                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6855                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6856                         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]);
6857                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6858                         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]);
6859                         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]);
6860                         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]);
6861                         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]);
6862                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6863                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6864                         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);
6865                         break;
6866                 case RENDERPATH_D3D9:
6867 #ifdef SUPPORTD3D
6868                         // 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...
6869                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6870                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6871                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6872                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6873                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6874                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6875                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6876                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6877                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6878                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6879                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6880                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6881                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6882                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6883 #endif
6884                         break;
6885                 case RENDERPATH_D3D10:
6886                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6887                         break;
6888                 case RENDERPATH_D3D11:
6889                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6890                         break;
6891                 case RENDERPATH_SOFT:
6892                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6893                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6894                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6895                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6896                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6897                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6898                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6899                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6900                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6901                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6902                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6903                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6904                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6905                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6906                         break;
6907                 default:
6908                         break;
6909                 }
6910                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6911                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6912                 break;
6913         case RENDERPATH_GL11:
6914         case RENDERPATH_GL13:
6915         case RENDERPATH_GLES1:
6916                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6917                 {
6918                         // apply a color tint to the whole view
6919                         R_ResetViewRendering2D(0, NULL, NULL);
6920                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6921                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6922                         R_SetupShader_Generic_NoTexture(false, true);
6923                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6924                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6925                 }
6926                 break;
6927         }
6928 }
6929
6930 matrix4x4_t r_waterscrollmatrix;
6931
6932 void R_UpdateFog(void)
6933 {
6934         // Nehahra fog
6935         if (gamemode == GAME_NEHAHRA)
6936         {
6937                 if (gl_fogenable.integer)
6938                 {
6939                         r_refdef.oldgl_fogenable = true;
6940                         r_refdef.fog_density = gl_fogdensity.value;
6941                         r_refdef.fog_red = gl_fogred.value;
6942                         r_refdef.fog_green = gl_foggreen.value;
6943                         r_refdef.fog_blue = gl_fogblue.value;
6944                         r_refdef.fog_alpha = 1;
6945                         r_refdef.fog_start = 0;
6946                         r_refdef.fog_end = gl_skyclip.value;
6947                         r_refdef.fog_height = 1<<30;
6948                         r_refdef.fog_fadedepth = 128;
6949                 }
6950                 else if (r_refdef.oldgl_fogenable)
6951                 {
6952                         r_refdef.oldgl_fogenable = false;
6953                         r_refdef.fog_density = 0;
6954                         r_refdef.fog_red = 0;
6955                         r_refdef.fog_green = 0;
6956                         r_refdef.fog_blue = 0;
6957                         r_refdef.fog_alpha = 0;
6958                         r_refdef.fog_start = 0;
6959                         r_refdef.fog_end = 0;
6960                         r_refdef.fog_height = 1<<30;
6961                         r_refdef.fog_fadedepth = 128;
6962                 }
6963         }
6964
6965         // fog parms
6966         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6967         r_refdef.fog_start = max(0, r_refdef.fog_start);
6968         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6969
6970         if (r_refdef.fog_density && r_drawfog.integer)
6971         {
6972                 r_refdef.fogenabled = true;
6973                 // this is the point where the fog reaches 0.9986 alpha, which we
6974                 // consider a good enough cutoff point for the texture
6975                 // (0.9986 * 256 == 255.6)
6976                 if (r_fog_exp2.integer)
6977                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6978                 else
6979                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6980                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6981                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6982                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6983                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6984                         R_BuildFogHeightTexture();
6985                 // fog color was already set
6986                 // update the fog texture
6987                 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)
6988                         R_BuildFogTexture();
6989                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6990                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6991         }
6992         else
6993                 r_refdef.fogenabled = false;
6994
6995         // fog color
6996         if (r_refdef.fog_density)
6997         {
6998                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6999                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7000                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7001
7002                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7003                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7004                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7005                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7006
7007                 {
7008                         vec3_t fogvec;
7009                         VectorCopy(r_refdef.fogcolor, fogvec);
7010                         //   color.rgb *= ContrastBoost * SceneBrightness;
7011                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7012                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7013                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7014                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7015                 }
7016         }
7017 }
7018
7019 void R_UpdateVariables(void)
7020 {
7021         R_Textures_Frame();
7022
7023         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7024
7025         r_refdef.farclip = r_farclip_base.value;
7026         if (r_refdef.scene.worldmodel)
7027                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7028         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7029
7030         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7031                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7032         r_refdef.polygonfactor = 0;
7033         r_refdef.polygonoffset = 0;
7034         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7035         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7036
7037         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7038         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7039         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7040         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7041         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7042         if (FAKELIGHT_ENABLED)
7043         {
7044                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7045         }
7046         else if (r_refdef.scene.worldmodel)
7047         {
7048                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7049         }
7050         if (r_showsurfaces.integer)
7051         {
7052                 r_refdef.scene.rtworld = false;
7053                 r_refdef.scene.rtworldshadows = false;
7054                 r_refdef.scene.rtdlight = false;
7055                 r_refdef.scene.rtdlightshadows = false;
7056                 r_refdef.lightmapintensity = 0;
7057         }
7058
7059         r_gpuskeletal = false;
7060         switch(vid.renderpath)
7061         {
7062         case RENDERPATH_GL20:
7063                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7064         case RENDERPATH_D3D9:
7065         case RENDERPATH_D3D10:
7066         case RENDERPATH_D3D11:
7067         case RENDERPATH_SOFT:
7068         case RENDERPATH_GLES2:
7069                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7070                 {
7071                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7072                         {
7073                                 // build GLSL gamma texture
7074 #define RAMPWIDTH 256
7075                                 unsigned short ramp[RAMPWIDTH * 3];
7076                                 unsigned char rampbgr[RAMPWIDTH][4];
7077                                 int i;
7078
7079                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7080
7081                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7082                                 for(i = 0; i < RAMPWIDTH; ++i)
7083                                 {
7084                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7085                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7086                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7087                                         rampbgr[i][3] = 0;
7088                                 }
7089                                 if (r_texture_gammaramps)
7090                                 {
7091                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7092                                 }
7093                                 else
7094                                 {
7095                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7096                                 }
7097                         }
7098                 }
7099                 else
7100                 {
7101                         // remove GLSL gamma texture
7102                 }
7103                 break;
7104         case RENDERPATH_GL11:
7105         case RENDERPATH_GL13:
7106         case RENDERPATH_GLES1:
7107                 break;
7108         }
7109 }
7110
7111 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7112 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7113 /*
7114 ================
7115 R_SelectScene
7116 ================
7117 */
7118 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7119         if( scenetype != r_currentscenetype ) {
7120                 // store the old scenetype
7121                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7122                 r_currentscenetype = scenetype;
7123                 // move in the new scene
7124                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7125         }
7126 }
7127
7128 /*
7129 ================
7130 R_GetScenePointer
7131 ================
7132 */
7133 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7134 {
7135         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7136         if( scenetype == r_currentscenetype ) {
7137                 return &r_refdef.scene;
7138         } else {
7139                 return &r_scenes_store[ scenetype ];
7140         }
7141 }
7142
7143 static int R_SortEntities_Compare(const void *ap, const void *bp)
7144 {
7145         const entity_render_t *a = *(const entity_render_t **)ap;
7146         const entity_render_t *b = *(const entity_render_t **)bp;
7147
7148         // 1. compare model
7149         if(a->model < b->model)
7150                 return -1;
7151         if(a->model > b->model)
7152                 return +1;
7153
7154         // 2. compare skin
7155         // TODO possibly calculate the REAL skinnum here first using
7156         // skinscenes?
7157         if(a->skinnum < b->skinnum)
7158                 return -1;
7159         if(a->skinnum > b->skinnum)
7160                 return +1;
7161
7162         // everything we compared is equal
7163         return 0;
7164 }
7165 static void R_SortEntities(void)
7166 {
7167         // below or equal 2 ents, sorting never gains anything
7168         if(r_refdef.scene.numentities <= 2)
7169                 return;
7170         // sort
7171         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7172 }
7173
7174 /*
7175 ================
7176 R_RenderView
7177 ================
7178 */
7179 int dpsoftrast_test;
7180 extern cvar_t r_shadow_bouncegrid;
7181 void R_RenderView(void)
7182 {
7183         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7184         int fbo;
7185         rtexture_t *depthtexture;
7186         rtexture_t *colortexture;
7187
7188         dpsoftrast_test = r_test.integer;
7189
7190         if (r_timereport_active)
7191                 R_TimeReport("start");
7192         r_textureframe++; // used only by R_GetCurrentTexture
7193         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7194
7195         if(R_CompileShader_CheckStaticParms())
7196                 R_GLSL_Restart_f();
7197
7198         if (!r_drawentities.integer)
7199                 r_refdef.scene.numentities = 0;
7200         else if (r_sortentities.integer)
7201                 R_SortEntities();
7202
7203         R_AnimCache_ClearCache();
7204         R_FrameData_NewFrame();
7205         R_BufferData_NewFrame();
7206
7207         /* adjust for stereo display */
7208         if(R_Stereo_Active())
7209         {
7210                 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);
7211                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7212         }
7213
7214         if (r_refdef.view.isoverlay)
7215         {
7216                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7217                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7218                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7219                 R_TimeReport("depthclear");
7220
7221                 r_refdef.view.showdebug = false;
7222
7223                 r_fb.water.enabled = false;
7224                 r_fb.water.numwaterplanes = 0;
7225
7226                 R_RenderScene(0, NULL, NULL);
7227
7228                 r_refdef.view.matrix = originalmatrix;
7229
7230                 CHECKGLERROR
7231                 return;
7232         }
7233
7234         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7235         {
7236                 r_refdef.view.matrix = originalmatrix;
7237                 return;
7238         }
7239
7240         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7241
7242         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7243                 // in sRGB fallback, behave similar to true sRGB: convert this
7244                 // value from linear to sRGB
7245                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7246
7247         R_RenderView_UpdateViewVectors();
7248
7249         R_Shadow_UpdateWorldLightSelection();
7250
7251         R_Bloom_StartFrame();
7252
7253         // apply bloom brightness offset
7254         if(r_fb.bloomtexture[0])
7255                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7256
7257         R_Water_StartFrame();
7258
7259         // now we probably have an fbo to render into
7260         fbo = r_fb.fbo;
7261         depthtexture = r_fb.depthtexture;
7262         colortexture = r_fb.colortexture;
7263
7264         CHECKGLERROR
7265         if (r_timereport_active)
7266                 R_TimeReport("viewsetup");
7267
7268         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7269
7270         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7271         {
7272                 R_ClearScreen(r_refdef.fogenabled);
7273                 if (r_timereport_active)
7274                         R_TimeReport("viewclear");
7275         }
7276         r_refdef.view.clear = true;
7277
7278         r_refdef.view.showdebug = true;
7279
7280         R_View_Update();
7281         if (r_timereport_active)
7282                 R_TimeReport("visibility");
7283
7284         R_AnimCache_CacheVisibleEntities();
7285         if (r_timereport_active)
7286                 R_TimeReport("animcache");
7287
7288         R_Shadow_UpdateBounceGridTexture();
7289         if (r_timereport_active && r_shadow_bouncegrid.integer)
7290                 R_TimeReport("bouncegrid");
7291
7292         r_fb.water.numwaterplanes = 0;
7293         if (r_fb.water.enabled)
7294                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7295
7296         R_RenderScene(fbo, depthtexture, colortexture);
7297         r_fb.water.numwaterplanes = 0;
7298
7299         R_BlendView(fbo, depthtexture, colortexture);
7300         if (r_timereport_active)
7301                 R_TimeReport("blendview");
7302
7303         GL_Scissor(0, 0, vid.width, vid.height);
7304         GL_ScissorTest(false);
7305
7306         r_refdef.view.matrix = originalmatrix;
7307
7308         CHECKGLERROR
7309 }
7310
7311 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7312 {
7313         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7314         {
7315                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7316                 if (r_timereport_active)
7317                         R_TimeReport("waterworld");
7318         }
7319
7320         // don't let sound skip if going slow
7321         if (r_refdef.scene.extraupdate)
7322                 S_ExtraUpdate ();
7323
7324         R_DrawModelsAddWaterPlanes();
7325         if (r_timereport_active)
7326                 R_TimeReport("watermodels");
7327
7328         if (r_fb.water.numwaterplanes)
7329         {
7330                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7331                 if (r_timereport_active)
7332                         R_TimeReport("waterscenes");
7333         }
7334 }
7335
7336 extern cvar_t cl_locs_show;
7337 static void R_DrawLocs(void);
7338 static void R_DrawEntityBBoxes(void);
7339 static void R_DrawModelDecals(void);
7340 extern cvar_t cl_decals_newsystem;
7341 extern qboolean r_shadow_usingdeferredprepass;
7342 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7343 {
7344         qboolean shadowmapping = false;
7345
7346         if (r_timereport_active)
7347                 R_TimeReport("beginscene");
7348
7349         r_refdef.stats[r_stat_renders]++;
7350
7351         R_UpdateFog();
7352
7353         // don't let sound skip if going slow
7354         if (r_refdef.scene.extraupdate)
7355                 S_ExtraUpdate ();
7356
7357         R_MeshQueue_BeginScene();
7358
7359         R_SkyStartFrame();
7360
7361         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);
7362
7363         if (r_timereport_active)
7364                 R_TimeReport("skystartframe");
7365
7366         if (cl.csqc_vidvars.drawworld)
7367         {
7368                 // don't let sound skip if going slow
7369                 if (r_refdef.scene.extraupdate)
7370                         S_ExtraUpdate ();
7371
7372                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7373                 {
7374                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7375                         if (r_timereport_active)
7376                                 R_TimeReport("worldsky");
7377                 }
7378
7379                 if (R_DrawBrushModelsSky() && r_timereport_active)
7380                         R_TimeReport("bmodelsky");
7381
7382                 if (skyrendermasked && skyrenderlater)
7383                 {
7384                         // we have to force off the water clipping plane while rendering sky
7385                         R_SetupView(false, fbo, depthtexture, colortexture);
7386                         R_Sky();
7387                         R_SetupView(true, fbo, depthtexture, colortexture);
7388                         if (r_timereport_active)
7389                                 R_TimeReport("sky");
7390                 }
7391         }
7392
7393         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7394         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7395                 R_Shadow_PrepareModelShadows();
7396         if (r_timereport_active)
7397                 R_TimeReport("preparelights");
7398
7399         if (R_Shadow_ShadowMappingEnabled())
7400                 shadowmapping = true;
7401
7402         if (r_shadow_usingdeferredprepass)
7403                 R_Shadow_DrawPrepass();
7404
7405         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7406         {
7407                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7408                 if (r_timereport_active)
7409                         R_TimeReport("worlddepth");
7410         }
7411         if (r_depthfirst.integer >= 2)
7412         {
7413                 R_DrawModelsDepth();
7414                 if (r_timereport_active)
7415                         R_TimeReport("modeldepth");
7416         }
7417
7418         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7419         {
7420                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7421                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7422                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7423                 // don't let sound skip if going slow
7424                 if (r_refdef.scene.extraupdate)
7425                         S_ExtraUpdate ();
7426         }
7427
7428         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7429         {
7430                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7431                 if (r_timereport_active)
7432                         R_TimeReport("world");
7433         }
7434
7435         // don't let sound skip if going slow
7436         if (r_refdef.scene.extraupdate)
7437                 S_ExtraUpdate ();
7438
7439         R_DrawModels();
7440         if (r_timereport_active)
7441                 R_TimeReport("models");
7442
7443         // don't let sound skip if going slow
7444         if (r_refdef.scene.extraupdate)
7445                 S_ExtraUpdate ();
7446
7447         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7448         {
7449                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7450                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7451                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7452                 // don't let sound skip if going slow
7453                 if (r_refdef.scene.extraupdate)
7454                         S_ExtraUpdate ();
7455         }
7456
7457         if (!r_shadow_usingdeferredprepass)
7458         {
7459                 R_Shadow_DrawLights();
7460                 if (r_timereport_active)
7461                         R_TimeReport("rtlights");
7462         }
7463
7464         // don't let sound skip if going slow
7465         if (r_refdef.scene.extraupdate)
7466                 S_ExtraUpdate ();
7467
7468         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7469         {
7470                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7471                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7472                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7473                 // don't let sound skip if going slow
7474                 if (r_refdef.scene.extraupdate)
7475                         S_ExtraUpdate ();
7476         }
7477
7478         if (cl.csqc_vidvars.drawworld)
7479         {
7480                 if (cl_decals_newsystem.integer)
7481                 {
7482                         R_DrawModelDecals();
7483                         if (r_timereport_active)
7484                                 R_TimeReport("modeldecals");
7485                 }
7486                 else
7487                 {
7488                         R_DrawDecals();
7489                         if (r_timereport_active)
7490                                 R_TimeReport("decals");
7491                 }
7492
7493                 R_DrawParticles();
7494                 if (r_timereport_active)
7495                         R_TimeReport("particles");
7496
7497                 R_DrawExplosions();
7498                 if (r_timereport_active)
7499                         R_TimeReport("explosions");
7500
7501                 R_DrawLightningBeams();
7502                 if (r_timereport_active)
7503                         R_TimeReport("lightning");
7504         }
7505
7506         if (cl.csqc_loaded)
7507                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7508
7509         if (r_refdef.view.showdebug)
7510         {
7511                 if (cl_locs_show.integer)
7512                 {
7513                         R_DrawLocs();
7514                         if (r_timereport_active)
7515                                 R_TimeReport("showlocs");
7516                 }
7517
7518                 if (r_drawportals.integer)
7519                 {
7520                         R_DrawPortals();
7521                         if (r_timereport_active)
7522                                 R_TimeReport("portals");
7523                 }
7524
7525                 if (r_showbboxes.value > 0)
7526                 {
7527                         R_DrawEntityBBoxes();
7528                         if (r_timereport_active)
7529                                 R_TimeReport("bboxes");
7530                 }
7531         }
7532
7533         if (r_transparent.integer)
7534         {
7535                 R_MeshQueue_RenderTransparent();
7536                 if (r_timereport_active)
7537                         R_TimeReport("drawtrans");
7538         }
7539
7540         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))
7541         {
7542                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7543                 if (r_timereport_active)
7544                         R_TimeReport("worlddebug");
7545                 R_DrawModelsDebug();
7546                 if (r_timereport_active)
7547                         R_TimeReport("modeldebug");
7548         }
7549
7550         if (cl.csqc_vidvars.drawworld)
7551         {
7552                 R_Shadow_DrawCoronas();
7553                 if (r_timereport_active)
7554                         R_TimeReport("coronas");
7555         }
7556
7557 #if 0
7558         {
7559                 GL_DepthTest(false);
7560                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7561                 GL_Color(1, 1, 1, 1);
7562                 qglBegin(GL_POLYGON);
7563                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7564                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7565                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7566                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7567                 qglEnd();
7568                 qglBegin(GL_POLYGON);
7569                 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]);
7570                 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]);
7571                 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]);
7572                 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]);
7573                 qglEnd();
7574                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7575         }
7576 #endif
7577
7578         // don't let sound skip if going slow
7579         if (r_refdef.scene.extraupdate)
7580                 S_ExtraUpdate ();
7581 }
7582
7583 static const unsigned short bboxelements[36] =
7584 {
7585         5, 1, 3, 5, 3, 7,
7586         6, 2, 0, 6, 0, 4,
7587         7, 3, 2, 7, 2, 6,
7588         4, 0, 1, 4, 1, 5,
7589         4, 5, 7, 4, 7, 6,
7590         1, 0, 2, 1, 2, 3,
7591 };
7592
7593 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7594 {
7595         int i;
7596         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7597
7598         RSurf_ActiveWorldEntity();
7599
7600         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7601         GL_DepthMask(false);
7602         GL_DepthRange(0, 1);
7603         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7604 //      R_Mesh_ResetTextureState();
7605
7606         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7607         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7608         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7609         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7610         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7611         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7612         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7613         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7614         R_FillColors(color4f, 8, cr, cg, cb, ca);
7615         if (r_refdef.fogenabled)
7616         {
7617                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7618                 {
7619                         f1 = RSurf_FogVertex(v);
7620                         f2 = 1 - f1;
7621                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7622                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7623                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7624                 }
7625         }
7626         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7627         R_Mesh_ResetTextureState();
7628         R_SetupShader_Generic_NoTexture(false, false);
7629         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7630 }
7631
7632 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7633 {
7634         prvm_prog_t *prog = SVVM_prog;
7635         int i;
7636         float color[4];
7637         prvm_edict_t *edict;
7638
7639         // this function draws bounding boxes of server entities
7640         if (!sv.active)
7641                 return;
7642
7643         GL_CullFace(GL_NONE);
7644         R_SetupShader_Generic_NoTexture(false, false);
7645
7646         for (i = 0;i < numsurfaces;i++)
7647         {
7648                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7649                 switch ((int)PRVM_serveredictfloat(edict, solid))
7650                 {
7651                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7652                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7653                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7654                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7655                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7656                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7657                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7658                 }
7659                 color[3] *= r_showbboxes.value;
7660                 color[3] = bound(0, color[3], 1);
7661                 GL_DepthTest(!r_showdisabledepthtest.integer);
7662                 GL_CullFace(r_refdef.view.cullface_front);
7663                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7664         }
7665 }
7666
7667 static void R_DrawEntityBBoxes(void)
7668 {
7669         int i;
7670         prvm_edict_t *edict;
7671         vec3_t center;
7672         prvm_prog_t *prog = SVVM_prog;
7673
7674         // this function draws bounding boxes of server entities
7675         if (!sv.active)
7676                 return;
7677
7678         for (i = 0;i < prog->num_edicts;i++)
7679         {
7680                 edict = PRVM_EDICT_NUM(i);
7681                 if (edict->priv.server->free)
7682                         continue;
7683                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7684                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7685                         continue;
7686                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7687                         continue;
7688                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7689                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7690         }
7691 }
7692
7693 static const int nomodelelement3i[24] =
7694 {
7695         5, 2, 0,
7696         5, 1, 2,
7697         5, 0, 3,
7698         5, 3, 1,
7699         0, 2, 4,
7700         2, 1, 4,
7701         3, 0, 4,
7702         1, 3, 4
7703 };
7704
7705 static const unsigned short nomodelelement3s[24] =
7706 {
7707         5, 2, 0,
7708         5, 1, 2,
7709         5, 0, 3,
7710         5, 3, 1,
7711         0, 2, 4,
7712         2, 1, 4,
7713         3, 0, 4,
7714         1, 3, 4
7715 };
7716
7717 static const float nomodelvertex3f[6*3] =
7718 {
7719         -16,   0,   0,
7720          16,   0,   0,
7721           0, -16,   0,
7722           0,  16,   0,
7723           0,   0, -16,
7724           0,   0,  16
7725 };
7726
7727 static const float nomodelcolor4f[6*4] =
7728 {
7729         0.0f, 0.0f, 0.5f, 1.0f,
7730         0.0f, 0.0f, 0.5f, 1.0f,
7731         0.0f, 0.5f, 0.0f, 1.0f,
7732         0.0f, 0.5f, 0.0f, 1.0f,
7733         0.5f, 0.0f, 0.0f, 1.0f,
7734         0.5f, 0.0f, 0.0f, 1.0f
7735 };
7736
7737 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7738 {
7739         int i;
7740         float f1, f2, *c;
7741         float color4f[6*4];
7742
7743         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);
7744
7745         // this is only called once per entity so numsurfaces is always 1, and
7746         // surfacelist is always {0}, so this code does not handle batches
7747
7748         if (rsurface.ent_flags & RENDER_ADDITIVE)
7749         {
7750                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7751                 GL_DepthMask(false);
7752         }
7753         else if (rsurface.colormod[3] < 1)
7754         {
7755                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7756                 GL_DepthMask(false);
7757         }
7758         else
7759         {
7760                 GL_BlendFunc(GL_ONE, GL_ZERO);
7761                 GL_DepthMask(true);
7762         }
7763         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7764         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7765         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7766         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7767         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7768         for (i = 0, c = color4f;i < 6;i++, c += 4)
7769         {
7770                 c[0] *= rsurface.colormod[0];
7771                 c[1] *= rsurface.colormod[1];
7772                 c[2] *= rsurface.colormod[2];
7773                 c[3] *= rsurface.colormod[3];
7774         }
7775         if (r_refdef.fogenabled)
7776         {
7777                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7778                 {
7779                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7780                         f2 = 1 - f1;
7781                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7782                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7783                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7784                 }
7785         }
7786 //      R_Mesh_ResetTextureState();
7787         R_SetupShader_Generic_NoTexture(false, false);
7788         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7789         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7790 }
7791
7792 void R_DrawNoModel(entity_render_t *ent)
7793 {
7794         vec3_t org;
7795         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7796         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7797                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7798         else
7799                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7800 }
7801
7802 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7803 {
7804         vec3_t right1, right2, diff, normal;
7805
7806         VectorSubtract (org2, org1, normal);
7807
7808         // calculate 'right' vector for start
7809         VectorSubtract (r_refdef.view.origin, org1, diff);
7810         CrossProduct (normal, diff, right1);
7811         VectorNormalize (right1);
7812
7813         // calculate 'right' vector for end
7814         VectorSubtract (r_refdef.view.origin, org2, diff);
7815         CrossProduct (normal, diff, right2);
7816         VectorNormalize (right2);
7817
7818         vert[ 0] = org1[0] + width * right1[0];
7819         vert[ 1] = org1[1] + width * right1[1];
7820         vert[ 2] = org1[2] + width * right1[2];
7821         vert[ 3] = org1[0] - width * right1[0];
7822         vert[ 4] = org1[1] - width * right1[1];
7823         vert[ 5] = org1[2] - width * right1[2];
7824         vert[ 6] = org2[0] - width * right2[0];
7825         vert[ 7] = org2[1] - width * right2[1];
7826         vert[ 8] = org2[2] - width * right2[2];
7827         vert[ 9] = org2[0] + width * right2[0];
7828         vert[10] = org2[1] + width * right2[1];
7829         vert[11] = org2[2] + width * right2[2];
7830 }
7831
7832 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)
7833 {
7834         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7835         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7836         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7837         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7838         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7839         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7840         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7841         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7842         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7843         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7844         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7845         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7846 }
7847
7848 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7849 {
7850         int i;
7851         float *vertex3f;
7852         float v[3];
7853         VectorSet(v, x, y, z);
7854         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7855                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7856                         break;
7857         if (i == mesh->numvertices)
7858         {
7859                 if (mesh->numvertices < mesh->maxvertices)
7860                 {
7861                         VectorCopy(v, vertex3f);
7862                         mesh->numvertices++;
7863                 }
7864                 return mesh->numvertices;
7865         }
7866         else
7867                 return i;
7868 }
7869
7870 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7871 {
7872         int i;
7873         int *e, element[3];
7874         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7875         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7876         e = mesh->element3i + mesh->numtriangles * 3;
7877         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7878         {
7879                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7880                 if (mesh->numtriangles < mesh->maxtriangles)
7881                 {
7882                         *e++ = element[0];
7883                         *e++ = element[1];
7884                         *e++ = element[2];
7885                         mesh->numtriangles++;
7886                 }
7887                 element[1] = element[2];
7888         }
7889 }
7890
7891 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7892 {
7893         int i;
7894         int *e, element[3];
7895         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7896         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7897         e = mesh->element3i + mesh->numtriangles * 3;
7898         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7899         {
7900                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7901                 if (mesh->numtriangles < mesh->maxtriangles)
7902                 {
7903                         *e++ = element[0];
7904                         *e++ = element[1];
7905                         *e++ = element[2];
7906                         mesh->numtriangles++;
7907                 }
7908                 element[1] = element[2];
7909         }
7910 }
7911
7912 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7913 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7914 {
7915         int planenum, planenum2;
7916         int w;
7917         int tempnumpoints;
7918         mplane_t *plane, *plane2;
7919         double maxdist;
7920         double temppoints[2][256*3];
7921         // figure out how large a bounding box we need to properly compute this brush
7922         maxdist = 0;
7923         for (w = 0;w < numplanes;w++)
7924                 maxdist = max(maxdist, fabs(planes[w].dist));
7925         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7926         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7927         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7928         {
7929                 w = 0;
7930                 tempnumpoints = 4;
7931                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7932                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7933                 {
7934                         if (planenum2 == planenum)
7935                                 continue;
7936                         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);
7937                         w = !w;
7938                 }
7939                 if (tempnumpoints < 3)
7940                         continue;
7941                 // generate elements forming a triangle fan for this polygon
7942                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7943         }
7944 }
7945
7946 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)
7947 {
7948         texturelayer_t *layer;
7949         layer = t->currentlayers + t->currentnumlayers++;
7950         layer->type = type;
7951         layer->depthmask = depthmask;
7952         layer->blendfunc1 = blendfunc1;
7953         layer->blendfunc2 = blendfunc2;
7954         layer->texture = texture;
7955         layer->texmatrix = *matrix;
7956         layer->color[0] = r;
7957         layer->color[1] = g;
7958         layer->color[2] = b;
7959         layer->color[3] = a;
7960 }
7961
7962 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7963 {
7964         if(parms[0] == 0 && parms[1] == 0)
7965                 return false;
7966         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7967                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7968                         return false;
7969         return true;
7970 }
7971
7972 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7973 {
7974         double index, f;
7975         index = parms[2] + rsurface.shadertime * parms[3];
7976         index -= floor(index);
7977         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7978         {
7979         default:
7980         case Q3WAVEFUNC_NONE:
7981         case Q3WAVEFUNC_NOISE:
7982         case Q3WAVEFUNC_COUNT:
7983                 f = 0;
7984                 break;
7985         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7986         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7987         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7988         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7989         case Q3WAVEFUNC_TRIANGLE:
7990                 index *= 4;
7991                 f = index - floor(index);
7992                 if (index < 1)
7993                 {
7994                         // f = f;
7995                 }
7996                 else if (index < 2)
7997                         f = 1 - f;
7998                 else if (index < 3)
7999                         f = -f;
8000                 else
8001                         f = -(1 - f);
8002                 break;
8003         }
8004         f = parms[0] + parms[1] * f;
8005         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8006                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8007         return (float) f;
8008 }
8009
8010 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8011 {
8012         int w, h, idx;
8013         double f;
8014         double offsetd[2];
8015         float tcmat[12];
8016         matrix4x4_t matrix, temp;
8017         switch(tcmod->tcmod)
8018         {
8019                 case Q3TCMOD_COUNT:
8020                 case Q3TCMOD_NONE:
8021                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8022                                 matrix = r_waterscrollmatrix;
8023                         else
8024                                 matrix = identitymatrix;
8025                         break;
8026                 case Q3TCMOD_ENTITYTRANSLATE:
8027                         // this is used in Q3 to allow the gamecode to control texcoord
8028                         // scrolling on the entity, which is not supported in darkplaces yet.
8029                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8030                         break;
8031                 case Q3TCMOD_ROTATE:
8032                         f = tcmod->parms[0] * rsurface.shadertime;
8033                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8034                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
8035                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8036                         break;
8037                 case Q3TCMOD_SCALE:
8038                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8039                         break;
8040                 case Q3TCMOD_SCROLL:
8041                         // extra care is needed because of precision breakdown with large values of time
8042                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8043                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8044                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8045                         break;
8046                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8047                         w = (int) tcmod->parms[0];
8048                         h = (int) tcmod->parms[1];
8049                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8050                         f = f - floor(f);
8051                         idx = (int) floor(f * w * h);
8052                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8053                         break;
8054                 case Q3TCMOD_STRETCH:
8055                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8056                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8057                         break;
8058                 case Q3TCMOD_TRANSFORM:
8059                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8060                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8061                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8062                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8063                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8064                         break;
8065                 case Q3TCMOD_TURBULENT:
8066                         // this is handled in the RSurf_PrepareVertices function
8067                         matrix = identitymatrix;
8068                         break;
8069         }
8070         temp = *texmatrix;
8071         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8072 }
8073
8074 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8075 {
8076         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8077         char name[MAX_QPATH];
8078         skinframe_t *skinframe;
8079         unsigned char pixels[296*194];
8080         strlcpy(cache->name, skinname, sizeof(cache->name));
8081         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8082         if (developer_loading.integer)
8083                 Con_Printf("loading %s\n", name);
8084         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8085         if (!skinframe || !skinframe->base)
8086         {
8087                 unsigned char *f;
8088                 fs_offset_t filesize;
8089                 skinframe = NULL;
8090                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8091                 if (f)
8092                 {
8093                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8094                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8095                         Mem_Free(f);
8096                 }
8097         }
8098         cache->skinframe = skinframe;
8099 }
8100
8101 texture_t *R_GetCurrentTexture(texture_t *t)
8102 {
8103         int i;
8104         const entity_render_t *ent = rsurface.entity;
8105         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8106         q3shaderinfo_layer_tcmod_t *tcmod;
8107
8108         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8109                 return t->currentframe;
8110         t->update_lastrenderframe = r_textureframe;
8111         t->update_lastrenderentity = (void *)ent;
8112
8113         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8114                 t->camera_entity = ent->entitynumber;
8115         else
8116                 t->camera_entity = 0;
8117
8118         // switch to an alternate material if this is a q1bsp animated material
8119         {
8120                 texture_t *texture = t;
8121                 int s = rsurface.ent_skinnum;
8122                 if ((unsigned int)s >= (unsigned int)model->numskins)
8123                         s = 0;
8124                 if (model->skinscenes)
8125                 {
8126                         if (model->skinscenes[s].framecount > 1)
8127                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8128                         else
8129                                 s = model->skinscenes[s].firstframe;
8130                 }
8131                 if (s > 0)
8132                         t = t + s * model->num_surfaces;
8133                 if (t->animated)
8134                 {
8135                         // use an alternate animation if the entity's frame is not 0,
8136                         // and only if the texture has an alternate animation
8137                         if (rsurface.ent_alttextures && t->anim_total[1])
8138                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8139                         else
8140                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8141                 }
8142                 texture->currentframe = t;
8143         }
8144
8145         // update currentskinframe to be a qw skin or animation frame
8146         if (rsurface.ent_qwskin >= 0)
8147         {
8148                 i = rsurface.ent_qwskin;
8149                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8150                 {
8151                         r_qwskincache_size = cl.maxclients;
8152                         if (r_qwskincache)
8153                                 Mem_Free(r_qwskincache);
8154                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8155                 }
8156                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8157                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8158                 t->currentskinframe = r_qwskincache[i].skinframe;
8159                 if (t->currentskinframe == NULL)
8160                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8161         }
8162         else if (t->numskinframes >= 2)
8163                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8164         if (t->backgroundnumskinframes >= 2)
8165                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8166
8167         t->currentmaterialflags = t->basematerialflags;
8168         t->currentalpha = rsurface.colormod[3];
8169         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8170                 t->currentalpha *= r_wateralpha.value;
8171         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8172                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8173         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8174                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8175         if (!(rsurface.ent_flags & RENDER_LIGHT))
8176                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8177         else if (FAKELIGHT_ENABLED)
8178         {
8179                 // no modellight if using fakelight for the map
8180         }
8181         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8182         {
8183                 // pick a model lighting mode
8184                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8185                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8186                 else
8187                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8188         }
8189         if (rsurface.ent_flags & RENDER_ADDITIVE)
8190                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8191         else if (t->currentalpha < 1)
8192                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8193         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8194         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8195                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8196         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8197                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8198         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8199                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8200         if (t->backgroundnumskinframes)
8201                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8202         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8203         {
8204                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8205                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8206         }
8207         else
8208                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8209         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8210         {
8211                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8212                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8213         }
8214         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8215                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8216
8217         // there is no tcmod
8218         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8219         {
8220                 t->currenttexmatrix = r_waterscrollmatrix;
8221                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8222         }
8223         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8224         {
8225                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8226                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8227         }
8228
8229         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8230                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8231         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8232                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8233
8234         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8235         if (t->currentskinframe->qpixels)
8236                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8237         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8238         if (!t->basetexture)
8239                 t->basetexture = r_texture_notexture;
8240         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8241         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8242         t->nmaptexture = t->currentskinframe->nmap;
8243         if (!t->nmaptexture)
8244                 t->nmaptexture = r_texture_blanknormalmap;
8245         t->glosstexture = r_texture_black;
8246         t->glowtexture = t->currentskinframe->glow;
8247         t->fogtexture = t->currentskinframe->fog;
8248         t->reflectmasktexture = t->currentskinframe->reflect;
8249         if (t->backgroundnumskinframes)
8250         {
8251                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8252                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8253                 t->backgroundglosstexture = r_texture_black;
8254                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8255                 if (!t->backgroundnmaptexture)
8256                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8257                 // make sure that if glow is going to be used, both textures are not NULL
8258                 if (!t->backgroundglowtexture && t->glowtexture)
8259                         t->backgroundglowtexture = r_texture_black;
8260                 if (!t->glowtexture && t->backgroundglowtexture)
8261                         t->glowtexture = r_texture_black;
8262         }
8263         else
8264         {
8265                 t->backgroundbasetexture = r_texture_white;
8266                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8267                 t->backgroundglosstexture = r_texture_black;
8268                 t->backgroundglowtexture = NULL;
8269         }
8270         t->specularpower = r_shadow_glossexponent.value;
8271         // TODO: store reference values for these in the texture?
8272         t->specularscale = 0;
8273         if (r_shadow_gloss.integer > 0)
8274         {
8275                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8276                 {
8277                         if (r_shadow_glossintensity.value > 0)
8278                         {
8279                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8280                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8281                                 t->specularscale = r_shadow_glossintensity.value;
8282                         }
8283                 }
8284                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8285                 {
8286                         t->glosstexture = r_texture_white;
8287                         t->backgroundglosstexture = r_texture_white;
8288                         t->specularscale = r_shadow_gloss2intensity.value;
8289                         t->specularpower = r_shadow_gloss2exponent.value;
8290                 }
8291         }
8292         t->specularscale *= t->specularscalemod;
8293         t->specularpower *= t->specularpowermod;
8294         t->rtlightambient = 0;
8295
8296         // lightmaps mode looks bad with dlights using actual texturing, so turn
8297         // off the colormap and glossmap, but leave the normalmap on as it still
8298         // accurately represents the shading involved
8299         if (gl_lightmaps.integer)
8300         {
8301                 t->basetexture = r_texture_grey128;
8302                 t->pantstexture = r_texture_black;
8303                 t->shirttexture = r_texture_black;
8304                 if (gl_lightmaps.integer < 2)
8305                         t->nmaptexture = r_texture_blanknormalmap;
8306                 t->glosstexture = r_texture_black;
8307                 t->glowtexture = NULL;
8308                 t->fogtexture = NULL;
8309                 t->reflectmasktexture = NULL;
8310                 t->backgroundbasetexture = NULL;
8311                 if (gl_lightmaps.integer < 2)
8312                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8313                 t->backgroundglosstexture = r_texture_black;
8314                 t->backgroundglowtexture = NULL;
8315                 t->specularscale = 0;
8316                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8317         }
8318
8319         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8320         VectorClear(t->dlightcolor);
8321         t->currentnumlayers = 0;
8322         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8323         {
8324                 int blendfunc1, blendfunc2;
8325                 qboolean depthmask;
8326                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8327                 {
8328                         blendfunc1 = GL_SRC_ALPHA;
8329                         blendfunc2 = GL_ONE;
8330                 }
8331                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8332                 {
8333                         blendfunc1 = GL_SRC_ALPHA;
8334                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8335                 }
8336                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8337                 {
8338                         blendfunc1 = t->customblendfunc[0];
8339                         blendfunc2 = t->customblendfunc[1];
8340                 }
8341                 else
8342                 {
8343                         blendfunc1 = GL_ONE;
8344                         blendfunc2 = GL_ZERO;
8345                 }
8346                 // don't colormod evilblend textures
8347                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8348                         VectorSet(t->lightmapcolor, 1, 1, 1);
8349                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8350                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8351                 {
8352                         // fullbright is not affected by r_refdef.lightmapintensity
8353                         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]);
8354                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8355                                 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]);
8356                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8357                                 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]);
8358                 }
8359                 else
8360                 {
8361                         vec3_t ambientcolor;
8362                         float colorscale;
8363                         // set the color tint used for lights affecting this surface
8364                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8365                         colorscale = 2;
8366                         // q3bsp has no lightmap updates, so the lightstylevalue that
8367                         // would normally be baked into the lightmap must be
8368                         // applied to the color
8369                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8370                         if (model->type == mod_brushq3)
8371                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8372                         colorscale *= r_refdef.lightmapintensity;
8373                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8374                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8375                         // basic lit geometry
8376                         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]);
8377                         // add pants/shirt if needed
8378                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8379                                 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]);
8380                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8381                                 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]);
8382                         // now add ambient passes if needed
8383                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8384                         {
8385                                 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]);
8386                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8387                                         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]);
8388                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8389                                         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]);
8390                         }
8391                 }
8392                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8393                         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]);
8394                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8395                 {
8396                         // if this is opaque use alpha blend which will darken the earlier
8397                         // passes cheaply.
8398                         //
8399                         // if this is an alpha blended material, all the earlier passes
8400                         // were darkened by fog already, so we only need to add the fog
8401                         // color ontop through the fog mask texture
8402                         //
8403                         // if this is an additive blended material, all the earlier passes
8404                         // were darkened by fog already, and we should not add fog color
8405                         // (because the background was not darkened, there is no fog color
8406                         // that was lost behind it).
8407                         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]);
8408                 }
8409         }
8410
8411         return t->currentframe;
8412 }
8413
8414 rsurfacestate_t rsurface;
8415
8416 void RSurf_ActiveWorldEntity(void)
8417 {
8418         dp_model_t *model = r_refdef.scene.worldmodel;
8419         //if (rsurface.entity == r_refdef.scene.worldentity)
8420         //      return;
8421         rsurface.entity = r_refdef.scene.worldentity;
8422         rsurface.skeleton = NULL;
8423         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8424         rsurface.ent_skinnum = 0;
8425         rsurface.ent_qwskin = -1;
8426         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8427         rsurface.shadertime = r_refdef.scene.time;
8428         rsurface.matrix = identitymatrix;
8429         rsurface.inversematrix = identitymatrix;
8430         rsurface.matrixscale = 1;
8431         rsurface.inversematrixscale = 1;
8432         R_EntityMatrix(&identitymatrix);
8433         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8434         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8435         rsurface.fograngerecip = r_refdef.fograngerecip;
8436         rsurface.fogheightfade = r_refdef.fogheightfade;
8437         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8438         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8439         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8440         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8441         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8442         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8443         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8444         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8445         rsurface.colormod[3] = 1;
8446         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);
8447         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8448         rsurface.frameblend[0].lerp = 1;
8449         rsurface.ent_alttextures = false;
8450         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8451         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8452         rsurface.entityskeletaltransform3x4 = NULL;
8453         rsurface.entityskeletaltransform3x4buffer = NULL;
8454         rsurface.entityskeletaltransform3x4offset = 0;
8455         rsurface.entityskeletaltransform3x4size = 0;;
8456         rsurface.entityskeletalnumtransforms = 0;
8457         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8458         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8459         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8460         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8461         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8462         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8463         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8464         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8465         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8466         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8467         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8468         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8469         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8470         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8471         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8472         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8473         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8475         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8476         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8477         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8478         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8479         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8480         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8481         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8482         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8484         rsurface.modelelement3i = model->surfmesh.data_element3i;
8485         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8486         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8487         rsurface.modelelement3s = model->surfmesh.data_element3s;
8488         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8489         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8490         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8491         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8492         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8493         rsurface.modelsurfaces = model->data_surfaces;
8494         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8495         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8496         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8497         rsurface.modelgeneratedvertex = false;
8498         rsurface.batchgeneratedvertex = false;
8499         rsurface.batchfirstvertex = 0;
8500         rsurface.batchnumvertices = 0;
8501         rsurface.batchfirsttriangle = 0;
8502         rsurface.batchnumtriangles = 0;
8503         rsurface.batchvertex3f  = NULL;
8504         rsurface.batchvertex3f_vertexbuffer = NULL;
8505         rsurface.batchvertex3f_bufferoffset = 0;
8506         rsurface.batchsvector3f = NULL;
8507         rsurface.batchsvector3f_vertexbuffer = NULL;
8508         rsurface.batchsvector3f_bufferoffset = 0;
8509         rsurface.batchtvector3f = NULL;
8510         rsurface.batchtvector3f_vertexbuffer = NULL;
8511         rsurface.batchtvector3f_bufferoffset = 0;
8512         rsurface.batchnormal3f  = NULL;
8513         rsurface.batchnormal3f_vertexbuffer = NULL;
8514         rsurface.batchnormal3f_bufferoffset = 0;
8515         rsurface.batchlightmapcolor4f = NULL;
8516         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8517         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8518         rsurface.batchtexcoordtexture2f = NULL;
8519         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8520         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8521         rsurface.batchtexcoordlightmap2f = NULL;
8522         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8523         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8524         rsurface.batchskeletalindex4ub = NULL;
8525         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8526         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8527         rsurface.batchskeletalweight4ub = NULL;
8528         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8529         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8530         rsurface.batchvertexmesh = NULL;
8531         rsurface.batchvertexmesh_vertexbuffer = NULL;
8532         rsurface.batchvertexmesh_bufferoffset = 0;
8533         rsurface.batchelement3i = NULL;
8534         rsurface.batchelement3i_indexbuffer = NULL;
8535         rsurface.batchelement3i_bufferoffset = 0;
8536         rsurface.batchelement3s = NULL;
8537         rsurface.batchelement3s_indexbuffer = NULL;
8538         rsurface.batchelement3s_bufferoffset = 0;
8539         rsurface.passcolor4f = NULL;
8540         rsurface.passcolor4f_vertexbuffer = NULL;
8541         rsurface.passcolor4f_bufferoffset = 0;
8542         rsurface.forcecurrenttextureupdate = false;
8543 }
8544
8545 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8546 {
8547         dp_model_t *model = ent->model;
8548         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8549         //      return;
8550         rsurface.entity = (entity_render_t *)ent;
8551         rsurface.skeleton = ent->skeleton;
8552         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8553         rsurface.ent_skinnum = ent->skinnum;
8554         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;
8555         rsurface.ent_flags = ent->flags;
8556         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8557         rsurface.matrix = ent->matrix;
8558         rsurface.inversematrix = ent->inversematrix;
8559         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8560         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8561         R_EntityMatrix(&rsurface.matrix);
8562         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8563         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8564         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8565         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8566         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8567         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8568         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8569         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8570         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8571         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8572         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8573         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8574         rsurface.colormod[3] = ent->alpha;
8575         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8576         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8577         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8578         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8579         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8580         if (ent->model->brush.submodel && !prepass)
8581         {
8582                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8583                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8584         }
8585         // if the animcache code decided it should use the shader path, skip the deform step
8586         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8587         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8588         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8589         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8590         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8591         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8592         {
8593                 if (ent->animcache_vertex3f)
8594                 {
8595                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8596                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8597                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8598                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8599                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8600                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8601                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8602                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8603                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8604                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8605                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8606                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8607                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8608                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8609                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8610                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8611                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8612                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8613                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8614                 }
8615                 else if (wanttangents)
8616                 {
8617                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8618                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8619                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8620                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8621                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8622                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8623                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8624                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8625                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8626                         rsurface.modelvertexmesh = NULL;
8627                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8628                         rsurface.modelvertexmesh_bufferoffset = 0;
8629                         rsurface.modelvertex3f_vertexbuffer = NULL;
8630                         rsurface.modelvertex3f_bufferoffset = 0;
8631                         rsurface.modelvertex3f_vertexbuffer = 0;
8632                         rsurface.modelvertex3f_bufferoffset = 0;
8633                         rsurface.modelsvector3f_vertexbuffer = 0;
8634                         rsurface.modelsvector3f_bufferoffset = 0;
8635                         rsurface.modeltvector3f_vertexbuffer = 0;
8636                         rsurface.modeltvector3f_bufferoffset = 0;
8637                         rsurface.modelnormal3f_vertexbuffer = 0;
8638                         rsurface.modelnormal3f_bufferoffset = 0;
8639                 }
8640                 else if (wantnormals)
8641                 {
8642                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8643                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8644                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8645                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8646                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8647                         rsurface.modelsvector3f = NULL;
8648                         rsurface.modeltvector3f = NULL;
8649                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8650                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8651                         rsurface.modelvertexmesh = NULL;
8652                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8653                         rsurface.modelvertexmesh_bufferoffset = 0;
8654                         rsurface.modelvertex3f_vertexbuffer = NULL;
8655                         rsurface.modelvertex3f_bufferoffset = 0;
8656                         rsurface.modelvertex3f_vertexbuffer = 0;
8657                         rsurface.modelvertex3f_bufferoffset = 0;
8658                         rsurface.modelsvector3f_vertexbuffer = 0;
8659                         rsurface.modelsvector3f_bufferoffset = 0;
8660                         rsurface.modeltvector3f_vertexbuffer = 0;
8661                         rsurface.modeltvector3f_bufferoffset = 0;
8662                         rsurface.modelnormal3f_vertexbuffer = 0;
8663                         rsurface.modelnormal3f_bufferoffset = 0;
8664                 }
8665                 else
8666                 {
8667                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8668                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8669                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8670                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8671                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8672                         rsurface.modelsvector3f = NULL;
8673                         rsurface.modeltvector3f = NULL;
8674                         rsurface.modelnormal3f = NULL;
8675                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8676                         rsurface.modelvertexmesh = NULL;
8677                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8678                         rsurface.modelvertexmesh_bufferoffset = 0;
8679                         rsurface.modelvertex3f_vertexbuffer = NULL;
8680                         rsurface.modelvertex3f_bufferoffset = 0;
8681                         rsurface.modelvertex3f_vertexbuffer = 0;
8682                         rsurface.modelvertex3f_bufferoffset = 0;
8683                         rsurface.modelsvector3f_vertexbuffer = 0;
8684                         rsurface.modelsvector3f_bufferoffset = 0;
8685                         rsurface.modeltvector3f_vertexbuffer = 0;
8686                         rsurface.modeltvector3f_bufferoffset = 0;
8687                         rsurface.modelnormal3f_vertexbuffer = 0;
8688                         rsurface.modelnormal3f_bufferoffset = 0;
8689                 }
8690                 rsurface.modelgeneratedvertex = true;
8691         }
8692         else
8693         {
8694                 if (rsurface.entityskeletaltransform3x4)
8695                 {
8696                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8697                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8698                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8699                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8700                 }
8701                 else
8702                 {
8703                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8704                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8705                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8706                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8707                 }
8708                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8709                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8710                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8711                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8712                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8713                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8714                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8715                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8716                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8717                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8718                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8719                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8720                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8721                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8722                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8723                 rsurface.modelgeneratedvertex = false;
8724         }
8725         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8726         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8727         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8728         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8729         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8730         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8731         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8732         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8733         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8734         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8735         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8736         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8737         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8738         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8739         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8740         rsurface.modelelement3i = model->surfmesh.data_element3i;
8741         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8742         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8743         rsurface.modelelement3s = model->surfmesh.data_element3s;
8744         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8745         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8746         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8747         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8748         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8749         rsurface.modelsurfaces = model->data_surfaces;
8750         rsurface.batchgeneratedvertex = false;
8751         rsurface.batchfirstvertex = 0;
8752         rsurface.batchnumvertices = 0;
8753         rsurface.batchfirsttriangle = 0;
8754         rsurface.batchnumtriangles = 0;
8755         rsurface.batchvertex3f  = NULL;
8756         rsurface.batchvertex3f_vertexbuffer = NULL;
8757         rsurface.batchvertex3f_bufferoffset = 0;
8758         rsurface.batchsvector3f = NULL;
8759         rsurface.batchsvector3f_vertexbuffer = NULL;
8760         rsurface.batchsvector3f_bufferoffset = 0;
8761         rsurface.batchtvector3f = NULL;
8762         rsurface.batchtvector3f_vertexbuffer = NULL;
8763         rsurface.batchtvector3f_bufferoffset = 0;
8764         rsurface.batchnormal3f  = NULL;
8765         rsurface.batchnormal3f_vertexbuffer = NULL;
8766         rsurface.batchnormal3f_bufferoffset = 0;
8767         rsurface.batchlightmapcolor4f = NULL;
8768         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8769         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8770         rsurface.batchtexcoordtexture2f = NULL;
8771         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8772         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8773         rsurface.batchtexcoordlightmap2f = NULL;
8774         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8775         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8776         rsurface.batchskeletalindex4ub = NULL;
8777         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8778         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8779         rsurface.batchskeletalweight4ub = NULL;
8780         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8781         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8782         rsurface.batchvertexmesh = NULL;
8783         rsurface.batchvertexmesh_vertexbuffer = NULL;
8784         rsurface.batchvertexmesh_bufferoffset = 0;
8785         rsurface.batchelement3i = NULL;
8786         rsurface.batchelement3i_indexbuffer = NULL;
8787         rsurface.batchelement3i_bufferoffset = 0;
8788         rsurface.batchelement3s = NULL;
8789         rsurface.batchelement3s_indexbuffer = NULL;
8790         rsurface.batchelement3s_bufferoffset = 0;
8791         rsurface.passcolor4f = NULL;
8792         rsurface.passcolor4f_vertexbuffer = NULL;
8793         rsurface.passcolor4f_bufferoffset = 0;
8794         rsurface.forcecurrenttextureupdate = false;
8795 }
8796
8797 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)
8798 {
8799         rsurface.entity = r_refdef.scene.worldentity;
8800         rsurface.skeleton = NULL;
8801         rsurface.ent_skinnum = 0;
8802         rsurface.ent_qwskin = -1;
8803         rsurface.ent_flags = entflags;
8804         rsurface.shadertime = r_refdef.scene.time - shadertime;
8805         rsurface.modelnumvertices = numvertices;
8806         rsurface.modelnumtriangles = numtriangles;
8807         rsurface.matrix = *matrix;
8808         rsurface.inversematrix = *inversematrix;
8809         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8810         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8811         R_EntityMatrix(&rsurface.matrix);
8812         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8813         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8814         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8815         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8816         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8817         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8818         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8819         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8820         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8821         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8822         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8823         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8824         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);
8825         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8826         rsurface.frameblend[0].lerp = 1;
8827         rsurface.ent_alttextures = false;
8828         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8829         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8830         rsurface.entityskeletaltransform3x4 = NULL;
8831         rsurface.entityskeletaltransform3x4buffer = NULL;
8832         rsurface.entityskeletaltransform3x4offset = 0;
8833         rsurface.entityskeletaltransform3x4size = 0;
8834         rsurface.entityskeletalnumtransforms = 0;
8835         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8836         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8837         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8838         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8839         if (wanttangents)
8840         {
8841                 rsurface.modelvertex3f = (float *)vertex3f;
8842                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8843                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8844                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8845         }
8846         else if (wantnormals)
8847         {
8848                 rsurface.modelvertex3f = (float *)vertex3f;
8849                 rsurface.modelsvector3f = NULL;
8850                 rsurface.modeltvector3f = NULL;
8851                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8852         }
8853         else
8854         {
8855                 rsurface.modelvertex3f = (float *)vertex3f;
8856                 rsurface.modelsvector3f = NULL;
8857                 rsurface.modeltvector3f = NULL;
8858                 rsurface.modelnormal3f = NULL;
8859         }
8860         rsurface.modelvertexmesh = NULL;
8861         rsurface.modelvertexmesh_vertexbuffer = NULL;
8862         rsurface.modelvertexmesh_bufferoffset = 0;
8863         rsurface.modelvertex3f_vertexbuffer = 0;
8864         rsurface.modelvertex3f_bufferoffset = 0;
8865         rsurface.modelsvector3f_vertexbuffer = 0;
8866         rsurface.modelsvector3f_bufferoffset = 0;
8867         rsurface.modeltvector3f_vertexbuffer = 0;
8868         rsurface.modeltvector3f_bufferoffset = 0;
8869         rsurface.modelnormal3f_vertexbuffer = 0;
8870         rsurface.modelnormal3f_bufferoffset = 0;
8871         rsurface.modelgeneratedvertex = true;
8872         rsurface.modellightmapcolor4f  = (float *)color4f;
8873         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8874         rsurface.modellightmapcolor4f_bufferoffset = 0;
8875         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8876         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8877         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8878         rsurface.modeltexcoordlightmap2f  = NULL;
8879         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8880         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8881         rsurface.modelskeletalindex4ub = NULL;
8882         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8883         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8884         rsurface.modelskeletalweight4ub = NULL;
8885         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8886         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8887         rsurface.modelelement3i = (int *)element3i;
8888         rsurface.modelelement3i_indexbuffer = NULL;
8889         rsurface.modelelement3i_bufferoffset = 0;
8890         rsurface.modelelement3s = (unsigned short *)element3s;
8891         rsurface.modelelement3s_indexbuffer = NULL;
8892         rsurface.modelelement3s_bufferoffset = 0;
8893         rsurface.modellightmapoffsets = NULL;
8894         rsurface.modelsurfaces = NULL;
8895         rsurface.batchgeneratedvertex = false;
8896         rsurface.batchfirstvertex = 0;
8897         rsurface.batchnumvertices = 0;
8898         rsurface.batchfirsttriangle = 0;
8899         rsurface.batchnumtriangles = 0;
8900         rsurface.batchvertex3f  = NULL;
8901         rsurface.batchvertex3f_vertexbuffer = NULL;
8902         rsurface.batchvertex3f_bufferoffset = 0;
8903         rsurface.batchsvector3f = NULL;
8904         rsurface.batchsvector3f_vertexbuffer = NULL;
8905         rsurface.batchsvector3f_bufferoffset = 0;
8906         rsurface.batchtvector3f = NULL;
8907         rsurface.batchtvector3f_vertexbuffer = NULL;
8908         rsurface.batchtvector3f_bufferoffset = 0;
8909         rsurface.batchnormal3f  = NULL;
8910         rsurface.batchnormal3f_vertexbuffer = NULL;
8911         rsurface.batchnormal3f_bufferoffset = 0;
8912         rsurface.batchlightmapcolor4f = NULL;
8913         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8914         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8915         rsurface.batchtexcoordtexture2f = NULL;
8916         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8917         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8918         rsurface.batchtexcoordlightmap2f = NULL;
8919         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8920         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8921         rsurface.batchskeletalindex4ub = NULL;
8922         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8923         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8924         rsurface.batchskeletalweight4ub = NULL;
8925         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8926         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8927         rsurface.batchvertexmesh = NULL;
8928         rsurface.batchvertexmesh_vertexbuffer = NULL;
8929         rsurface.batchvertexmesh_bufferoffset = 0;
8930         rsurface.batchelement3i = NULL;
8931         rsurface.batchelement3i_indexbuffer = NULL;
8932         rsurface.batchelement3i_bufferoffset = 0;
8933         rsurface.batchelement3s = NULL;
8934         rsurface.batchelement3s_indexbuffer = NULL;
8935         rsurface.batchelement3s_bufferoffset = 0;
8936         rsurface.passcolor4f = NULL;
8937         rsurface.passcolor4f_vertexbuffer = NULL;
8938         rsurface.passcolor4f_bufferoffset = 0;
8939         rsurface.forcecurrenttextureupdate = true;
8940
8941         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8942         {
8943                 if ((wantnormals || wanttangents) && !normal3f)
8944                 {
8945                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8946                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8947                 }
8948                 if (wanttangents && !svector3f)
8949                 {
8950                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8951                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8952                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8953                 }
8954         }
8955 }
8956
8957 float RSurf_FogPoint(const float *v)
8958 {
8959         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8960         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8961         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8962         float FogHeightFade = r_refdef.fogheightfade;
8963         float fogfrac;
8964         unsigned int fogmasktableindex;
8965         if (r_refdef.fogplaneviewabove)
8966                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8967         else
8968                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8969         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8970         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8971 }
8972
8973 float RSurf_FogVertex(const float *v)
8974 {
8975         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8976         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8977         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8978         float FogHeightFade = rsurface.fogheightfade;
8979         float fogfrac;
8980         unsigned int fogmasktableindex;
8981         if (r_refdef.fogplaneviewabove)
8982                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8983         else
8984                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8985         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8986         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8987 }
8988
8989 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8990 {
8991         int i;
8992         for (i = 0;i < numelements;i++)
8993                 outelement3i[i] = inelement3i[i] + adjust;
8994 }
8995
8996 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8997 extern cvar_t gl_vbo;
8998 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8999 {
9000         int deformindex;
9001         int firsttriangle;
9002         int numtriangles;
9003         int firstvertex;
9004         int endvertex;
9005         int numvertices;
9006         int surfacefirsttriangle;
9007         int surfacenumtriangles;
9008         int surfacefirstvertex;
9009         int surfaceendvertex;
9010         int surfacenumvertices;
9011         int batchnumsurfaces = texturenumsurfaces;
9012         int batchnumvertices;
9013         int batchnumtriangles;
9014         int needsupdate;
9015         int i, j;
9016         qboolean gaps;
9017         qboolean dynamicvertex;
9018         float amplitude;
9019         float animpos;
9020         float scale;
9021         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9022         float waveparms[4];
9023         unsigned char *ub;
9024         q3shaderinfo_deform_t *deform;
9025         const msurface_t *surface, *firstsurface;
9026         r_vertexmesh_t *vertexmesh;
9027         if (!texturenumsurfaces)
9028                 return;
9029         // find vertex range of this surface batch
9030         gaps = false;
9031         firstsurface = texturesurfacelist[0];
9032         firsttriangle = firstsurface->num_firsttriangle;
9033         batchnumvertices = 0;
9034         batchnumtriangles = 0;
9035         firstvertex = endvertex = firstsurface->num_firstvertex;
9036         for (i = 0;i < texturenumsurfaces;i++)
9037         {
9038                 surface = texturesurfacelist[i];
9039                 if (surface != firstsurface + i)
9040                         gaps = true;
9041                 surfacefirstvertex = surface->num_firstvertex;
9042                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9043                 surfacenumvertices = surface->num_vertices;
9044                 surfacenumtriangles = surface->num_triangles;
9045                 if (firstvertex > surfacefirstvertex)
9046                         firstvertex = surfacefirstvertex;
9047                 if (endvertex < surfaceendvertex)
9048                         endvertex = surfaceendvertex;
9049                 batchnumvertices += surfacenumvertices;
9050                 batchnumtriangles += surfacenumtriangles;
9051         }
9052
9053         r_refdef.stats[r_stat_batch_batches]++;
9054         if (gaps)
9055                 r_refdef.stats[r_stat_batch_withgaps]++;
9056         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9057         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9058         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9059
9060         // we now know the vertex range used, and if there are any gaps in it
9061         rsurface.batchfirstvertex = firstvertex;
9062         rsurface.batchnumvertices = endvertex - firstvertex;
9063         rsurface.batchfirsttriangle = firsttriangle;
9064         rsurface.batchnumtriangles = batchnumtriangles;
9065
9066         // this variable holds flags for which properties have been updated that
9067         // may require regenerating vertexmesh array...
9068         needsupdate = 0;
9069
9070         // check if any dynamic vertex processing must occur
9071         dynamicvertex = false;
9072
9073         // a cvar to force the dynamic vertex path to be taken, for debugging
9074         if (r_batch_debugdynamicvertexpath.integer)
9075         {
9076                 if (!dynamicvertex)
9077                 {
9078                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9079                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9080                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9081                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9082                 }
9083                 dynamicvertex = true;
9084         }
9085
9086         // if there is a chance of animated vertex colors, it's a dynamic batch
9087         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9088         {
9089                 if (!dynamicvertex)
9090                 {
9091                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9092                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9093                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9094                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9095                 }
9096                 dynamicvertex = true;
9097                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9098         }
9099
9100         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9101         {
9102                 switch (deform->deform)
9103                 {
9104                 default:
9105                 case Q3DEFORM_PROJECTIONSHADOW:
9106                 case Q3DEFORM_TEXT0:
9107                 case Q3DEFORM_TEXT1:
9108                 case Q3DEFORM_TEXT2:
9109                 case Q3DEFORM_TEXT3:
9110                 case Q3DEFORM_TEXT4:
9111                 case Q3DEFORM_TEXT5:
9112                 case Q3DEFORM_TEXT6:
9113                 case Q3DEFORM_TEXT7:
9114                 case Q3DEFORM_NONE:
9115                         break;
9116                 case Q3DEFORM_AUTOSPRITE:
9117                         if (!dynamicvertex)
9118                         {
9119                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9120                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9121                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9122                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9123                         }
9124                         dynamicvertex = true;
9125                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9126                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9127                         break;
9128                 case Q3DEFORM_AUTOSPRITE2:
9129                         if (!dynamicvertex)
9130                         {
9131                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9132                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9133                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9134                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9135                         }
9136                         dynamicvertex = true;
9137                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9138                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9139                         break;
9140                 case Q3DEFORM_NORMAL:
9141                         if (!dynamicvertex)
9142                         {
9143                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9144                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9145                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9146                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9147                         }
9148                         dynamicvertex = true;
9149                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9150                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9151                         break;
9152                 case Q3DEFORM_WAVE:
9153                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9154                                 break; // if wavefunc is a nop, ignore this transform
9155                         if (!dynamicvertex)
9156                         {
9157                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9158                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9159                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9160                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9161                         }
9162                         dynamicvertex = true;
9163                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9164                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9165                         break;
9166                 case Q3DEFORM_BULGE:
9167                         if (!dynamicvertex)
9168                         {
9169                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9170                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9171                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9172                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9173                         }
9174                         dynamicvertex = true;
9175                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9176                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9177                         break;
9178                 case Q3DEFORM_MOVE:
9179                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9180                                 break; // if wavefunc is a nop, ignore this transform
9181                         if (!dynamicvertex)
9182                         {
9183                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9184                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9185                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9186                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9187                         }
9188                         dynamicvertex = true;
9189                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9190                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9191                         break;
9192                 }
9193         }
9194         switch(rsurface.texture->tcgen.tcgen)
9195         {
9196         default:
9197         case Q3TCGEN_TEXTURE:
9198                 break;
9199         case Q3TCGEN_LIGHTMAP:
9200                 if (!dynamicvertex)
9201                 {
9202                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9203                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9204                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9205                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9206                 }
9207                 dynamicvertex = true;
9208                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9209                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9210                 break;
9211         case Q3TCGEN_VECTOR:
9212                 if (!dynamicvertex)
9213                 {
9214                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9215                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9216                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9217                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9218                 }
9219                 dynamicvertex = true;
9220                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9221                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9222                 break;
9223         case Q3TCGEN_ENVIRONMENT:
9224                 if (!dynamicvertex)
9225                 {
9226                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9227                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9228                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9229                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9230                 }
9231                 dynamicvertex = true;
9232                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9233                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9234                 break;
9235         }
9236         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9237         {
9238                 if (!dynamicvertex)
9239                 {
9240                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9241                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9242                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9243                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9244                 }
9245                 dynamicvertex = true;
9246                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9247                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9248         }
9249
9250         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9251         {
9252                 if (!dynamicvertex)
9253                 {
9254                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9255                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9256                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9257                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9258                 }
9259                 dynamicvertex = true;
9260                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9261         }
9262
9263         // when the model data has no vertex buffer (dynamic mesh), we need to
9264         // eliminate gaps
9265         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9266                 batchneed |= BATCHNEED_NOGAPS;
9267
9268         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9269         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9270         // we ensure this by treating the vertex batch as dynamic...
9271         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9272         {
9273                 if (!dynamicvertex)
9274                 {
9275                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9276                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9277                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9278                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9279                 }
9280                 dynamicvertex = true;
9281         }
9282
9283         if (dynamicvertex)
9284         {
9285                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9286                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9287                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9288                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9289                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9290                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9291                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9292                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9293         }
9294
9295         // if needsupdate, we have to do a dynamic vertex batch for sure
9296         if (needsupdate & batchneed)
9297         {
9298                 if (!dynamicvertex)
9299                 {
9300                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9301                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9302                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9303                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9304                 }
9305                 dynamicvertex = true;
9306         }
9307
9308         // see if we need to build vertexmesh from arrays
9309         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9310         {
9311                 if (!dynamicvertex)
9312                 {
9313                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9314                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9315                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9316                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9317                 }
9318                 dynamicvertex = true;
9319         }
9320
9321         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9322         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9323                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9324
9325         rsurface.batchvertex3f = rsurface.modelvertex3f;
9326         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9327         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9328         rsurface.batchsvector3f = rsurface.modelsvector3f;
9329         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9330         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9331         rsurface.batchtvector3f = rsurface.modeltvector3f;
9332         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9333         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9334         rsurface.batchnormal3f = rsurface.modelnormal3f;
9335         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9336         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9337         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9338         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9339         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9340         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9341         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9342         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9343         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9344         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9345         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9346         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9347         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9348         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9349         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9350         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9351         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9352         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9353         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9354         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9355         rsurface.batchelement3i = rsurface.modelelement3i;
9356         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9357         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9358         rsurface.batchelement3s = rsurface.modelelement3s;
9359         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9360         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9361         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9362         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9363         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9364         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9365         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9366
9367         // if any dynamic vertex processing has to occur in software, we copy the
9368         // entire surface list together before processing to rebase the vertices
9369         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9370         //
9371         // if any gaps exist and we do not have a static vertex buffer, we have to
9372         // copy the surface list together to avoid wasting upload bandwidth on the
9373         // vertices in the gaps.
9374         //
9375         // if gaps exist and we have a static vertex buffer, we can choose whether
9376         // to combine the index buffer ranges into one dynamic index buffer or
9377         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9378         //
9379         // in many cases the batch is reduced to one draw call.
9380
9381         rsurface.batchmultidraw = false;
9382         rsurface.batchmultidrawnumsurfaces = 0;
9383         rsurface.batchmultidrawsurfacelist = NULL;
9384
9385         if (!dynamicvertex)
9386         {
9387                 // static vertex data, just set pointers...
9388                 rsurface.batchgeneratedvertex = false;
9389                 // if there are gaps, we want to build a combined index buffer,
9390                 // otherwise use the original static buffer with an appropriate offset
9391                 if (gaps)
9392                 {
9393                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9394                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9395                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9396                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9397                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9398                         {
9399                                 rsurface.batchmultidraw = true;
9400                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9401                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9402                                 return;
9403                         }
9404                         // build a new triangle elements array for this batch
9405                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9406                         rsurface.batchfirsttriangle = 0;
9407                         numtriangles = 0;
9408                         for (i = 0;i < texturenumsurfaces;i++)
9409                         {
9410                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9411                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9412                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9413                                 numtriangles += surfacenumtriangles;
9414                         }
9415                         rsurface.batchelement3i_indexbuffer = NULL;
9416                         rsurface.batchelement3i_bufferoffset = 0;
9417                         rsurface.batchelement3s = NULL;
9418                         rsurface.batchelement3s_indexbuffer = NULL;
9419                         rsurface.batchelement3s_bufferoffset = 0;
9420                         if (endvertex <= 65536)
9421                         {
9422                                 // make a 16bit (unsigned short) index array if possible
9423                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9424                                 for (i = 0;i < numtriangles*3;i++)
9425                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9426                         }
9427                         // upload buffer data for the copytriangles batch
9428                         if (vid.forcevbo || (r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object))
9429                         {
9430                                 if (rsurface.batchelement3s)
9431                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset, !vid.forcevbo);
9432                                 else if (rsurface.batchelement3i)
9433                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset, !vid.forcevbo);
9434                         }
9435                 }
9436                 else
9437                 {
9438                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9439                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9440                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9441                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9442                 }
9443                 return;
9444         }
9445
9446         // something needs software processing, do it for real...
9447         // we only directly handle separate array data in this case and then
9448         // generate interleaved data if needed...
9449         rsurface.batchgeneratedvertex = true;
9450         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9451         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9452         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9453         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9454
9455         // now copy the vertex data into a combined array and make an index array
9456         // (this is what Quake3 does all the time)
9457         // we also apply any skeletal animation here that would have been done in
9458         // the vertex shader, because most of the dynamic vertex animation cases
9459         // need actual vertex positions and normals
9460         //if (dynamicvertex)
9461         {
9462                 rsurface.batchvertexmesh = NULL;
9463                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9464                 rsurface.batchvertexmesh_bufferoffset = 0;
9465                 rsurface.batchvertex3f = NULL;
9466                 rsurface.batchvertex3f_vertexbuffer = NULL;
9467                 rsurface.batchvertex3f_bufferoffset = 0;
9468                 rsurface.batchsvector3f = NULL;
9469                 rsurface.batchsvector3f_vertexbuffer = NULL;
9470                 rsurface.batchsvector3f_bufferoffset = 0;
9471                 rsurface.batchtvector3f = NULL;
9472                 rsurface.batchtvector3f_vertexbuffer = NULL;
9473                 rsurface.batchtvector3f_bufferoffset = 0;
9474                 rsurface.batchnormal3f = NULL;
9475                 rsurface.batchnormal3f_vertexbuffer = NULL;
9476                 rsurface.batchnormal3f_bufferoffset = 0;
9477                 rsurface.batchlightmapcolor4f = NULL;
9478                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9479                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9480                 rsurface.batchtexcoordtexture2f = NULL;
9481                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9482                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9483                 rsurface.batchtexcoordlightmap2f = NULL;
9484                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9485                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9486                 rsurface.batchskeletalindex4ub = NULL;
9487                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9488                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9489                 rsurface.batchskeletalweight4ub = NULL;
9490                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9491                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9492                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9493                 rsurface.batchelement3i_indexbuffer = NULL;
9494                 rsurface.batchelement3i_bufferoffset = 0;
9495                 rsurface.batchelement3s = NULL;
9496                 rsurface.batchelement3s_indexbuffer = NULL;
9497                 rsurface.batchelement3s_bufferoffset = 0;
9498                 rsurface.batchskeletaltransform3x4buffer = NULL;
9499                 rsurface.batchskeletaltransform3x4offset = 0;
9500                 rsurface.batchskeletaltransform3x4size = 0;
9501                 // we'll only be setting up certain arrays as needed
9502                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9503                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9504                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9505                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9506                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9507                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9508                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9509                 {
9510                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9511                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9512                 }
9513                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9514                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9515                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9516                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9517                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9518                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9519                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9520                 {
9521                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9522                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9523                 }
9524                 numvertices = 0;
9525                 numtriangles = 0;
9526                 for (i = 0;i < texturenumsurfaces;i++)
9527                 {
9528                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9529                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9530                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9531                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9532                         // copy only the data requested
9533                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9534                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9535                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9536                         {
9537                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9538                                 {
9539                                         if (rsurface.batchvertex3f)
9540                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9541                                         else
9542                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9543                                 }
9544                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9545                                 {
9546                                         if (rsurface.modelnormal3f)
9547                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9548                                         else
9549                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9550                                 }
9551                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9552                                 {
9553                                         if (rsurface.modelsvector3f)
9554                                         {
9555                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9556                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9557                                         }
9558                                         else
9559                                         {
9560                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9561                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9562                                         }
9563                                 }
9564                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9565                                 {
9566                                         if (rsurface.modellightmapcolor4f)
9567                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9568                                         else
9569                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9570                                 }
9571                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9572                                 {
9573                                         if (rsurface.modeltexcoordtexture2f)
9574                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9575                                         else
9576                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9577                                 }
9578                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9579                                 {
9580                                         if (rsurface.modeltexcoordlightmap2f)
9581                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9582                                         else
9583                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9584                                 }
9585                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9586                                 {
9587                                         if (rsurface.modelskeletalindex4ub)
9588                                         {
9589                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9590                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9591                                         }
9592                                         else
9593                                         {
9594                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9595                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9596                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9597                                                 for (j = 0;j < surfacenumvertices;j++)
9598                                                         ub[j*4] = 255;
9599                                         }
9600                                 }
9601                         }
9602                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9603                         numvertices += surfacenumvertices;
9604                         numtriangles += surfacenumtriangles;
9605                 }
9606
9607                 // generate a 16bit index array as well if possible
9608                 // (in general, dynamic batches fit)
9609                 if (numvertices <= 65536)
9610                 {
9611                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9612                         for (i = 0;i < numtriangles*3;i++)
9613                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9614                 }
9615
9616                 // since we've copied everything, the batch now starts at 0
9617                 rsurface.batchfirstvertex = 0;
9618                 rsurface.batchnumvertices = batchnumvertices;
9619                 rsurface.batchfirsttriangle = 0;
9620                 rsurface.batchnumtriangles = batchnumtriangles;
9621         }
9622
9623         // apply skeletal animation that would have been done in the vertex shader
9624         if (rsurface.batchskeletaltransform3x4)
9625         {
9626                 const unsigned char *si;
9627                 const unsigned char *sw;
9628                 const float *t[4];
9629                 const float *b = rsurface.batchskeletaltransform3x4;
9630                 float *vp, *vs, *vt, *vn;
9631                 float w[4];
9632                 float m[3][4], n[3][4];
9633                 float tp[3], ts[3], tt[3], tn[3];
9634                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9635                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9636                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9637                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9638                 si = rsurface.batchskeletalindex4ub;
9639                 sw = rsurface.batchskeletalweight4ub;
9640                 vp = rsurface.batchvertex3f;
9641                 vs = rsurface.batchsvector3f;
9642                 vt = rsurface.batchtvector3f;
9643                 vn = rsurface.batchnormal3f;
9644                 memset(m[0], 0, sizeof(m));
9645                 memset(n[0], 0, sizeof(n));
9646                 for (i = 0;i < batchnumvertices;i++)
9647                 {
9648                         t[0] = b + si[0]*12;
9649                         if (sw[0] == 255)
9650                         {
9651                                 // common case - only one matrix
9652                                 m[0][0] = t[0][ 0];
9653                                 m[0][1] = t[0][ 1];
9654                                 m[0][2] = t[0][ 2];
9655                                 m[0][3] = t[0][ 3];
9656                                 m[1][0] = t[0][ 4];
9657                                 m[1][1] = t[0][ 5];
9658                                 m[1][2] = t[0][ 6];
9659                                 m[1][3] = t[0][ 7];
9660                                 m[2][0] = t[0][ 8];
9661                                 m[2][1] = t[0][ 9];
9662                                 m[2][2] = t[0][10];
9663                                 m[2][3] = t[0][11];
9664                         }
9665                         else if (sw[2] + sw[3])
9666                         {
9667                                 // blend 4 matrices
9668                                 t[1] = b + si[1]*12;
9669                                 t[2] = b + si[2]*12;
9670                                 t[3] = b + si[3]*12;
9671                                 w[0] = sw[0] * (1.0f / 255.0f);
9672                                 w[1] = sw[1] * (1.0f / 255.0f);
9673                                 w[2] = sw[2] * (1.0f / 255.0f);
9674                                 w[3] = sw[3] * (1.0f / 255.0f);
9675                                 // blend the matrices
9676                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9677                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9678                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9679                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9680                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9681                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9682                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9683                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9684                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9685                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9686                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9687                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9688                         }
9689                         else
9690                         {
9691                                 // blend 2 matrices
9692                                 t[1] = b + si[1]*12;
9693                                 w[0] = sw[0] * (1.0f / 255.0f);
9694                                 w[1] = sw[1] * (1.0f / 255.0f);
9695                                 // blend the matrices
9696                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9697                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9698                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9699                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9700                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9701                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9702                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9703                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9704                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9705                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9706                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9707                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9708                         }
9709                         si += 4;
9710                         sw += 4;
9711                         // modify the vertex
9712                         VectorCopy(vp, tp);
9713                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9714                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9715                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9716                         vp += 3;
9717                         if (vn)
9718                         {
9719                                 // the normal transformation matrix is a set of cross products...
9720                                 CrossProduct(m[1], m[2], n[0]);
9721                                 CrossProduct(m[2], m[0], n[1]);
9722                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9723                                 VectorCopy(vn, tn);
9724                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9725                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9726                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9727                                 VectorNormalize(vn);
9728                                 vn += 3;
9729                                 if (vs)
9730                                 {
9731                                         VectorCopy(vs, ts);
9732                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9733                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9734                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9735                                         VectorNormalize(vs);
9736                                         vs += 3;
9737                                         VectorCopy(vt, tt);
9738                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9739                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9740                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9741                                         VectorNormalize(vt);
9742                                         vt += 3;
9743                                 }
9744                         }
9745                 }
9746                 rsurface.batchskeletaltransform3x4 = NULL;
9747                 rsurface.batchskeletalnumtransforms = 0;
9748         }
9749
9750         // q1bsp surfaces rendered in vertex color mode have to have colors
9751         // calculated based on lightstyles
9752         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9753         {
9754                 // generate color arrays for the surfaces in this list
9755                 int c[4];
9756                 int scale;
9757                 int size3;
9758                 const int *offsets;
9759                 const unsigned char *lm;
9760                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9761                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9762                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9763                 numvertices = 0;
9764                 for (i = 0;i < texturenumsurfaces;i++)
9765                 {
9766                         surface = texturesurfacelist[i];
9767                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9768                         surfacenumvertices = surface->num_vertices;
9769                         if (surface->lightmapinfo->samples)
9770                         {
9771                                 for (j = 0;j < surfacenumvertices;j++)
9772                                 {
9773                                         lm = surface->lightmapinfo->samples + offsets[j];
9774                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9775                                         VectorScale(lm, scale, c);
9776                                         if (surface->lightmapinfo->styles[1] != 255)
9777                                         {
9778                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9779                                                 lm += size3;
9780                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9781                                                 VectorMA(c, scale, lm, c);
9782                                                 if (surface->lightmapinfo->styles[2] != 255)
9783                                                 {
9784                                                         lm += size3;
9785                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9786                                                         VectorMA(c, scale, lm, c);
9787                                                         if (surface->lightmapinfo->styles[3] != 255)
9788                                                         {
9789                                                                 lm += size3;
9790                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9791                                                                 VectorMA(c, scale, lm, c);
9792                                                         }
9793                                                 }
9794                                         }
9795                                         c[0] >>= 7;
9796                                         c[1] >>= 7;
9797                                         c[2] >>= 7;
9798                                         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);
9799                                         numvertices++;
9800                                 }
9801                         }
9802                         else
9803                         {
9804                                 for (j = 0;j < surfacenumvertices;j++)
9805                                 {
9806                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9807                                         numvertices++;
9808                                 }
9809                         }
9810                 }
9811         }
9812
9813         // if vertices are deformed (sprite flares and things in maps, possibly
9814         // water waves, bulges and other deformations), modify the copied vertices
9815         // in place
9816         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9817         {
9818                 switch (deform->deform)
9819                 {
9820                 default:
9821                 case Q3DEFORM_PROJECTIONSHADOW:
9822                 case Q3DEFORM_TEXT0:
9823                 case Q3DEFORM_TEXT1:
9824                 case Q3DEFORM_TEXT2:
9825                 case Q3DEFORM_TEXT3:
9826                 case Q3DEFORM_TEXT4:
9827                 case Q3DEFORM_TEXT5:
9828                 case Q3DEFORM_TEXT6:
9829                 case Q3DEFORM_TEXT7:
9830                 case Q3DEFORM_NONE:
9831                         break;
9832                 case Q3DEFORM_AUTOSPRITE:
9833                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9834                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9835                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9836                         VectorNormalize(newforward);
9837                         VectorNormalize(newright);
9838                         VectorNormalize(newup);
9839 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9840 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9841 //                      rsurface.batchvertex3f_bufferoffset = 0;
9842 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9843 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9844 //                      rsurface.batchsvector3f_bufferoffset = 0;
9845 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9846 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9847 //                      rsurface.batchtvector3f_bufferoffset = 0;
9848 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9849 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9850 //                      rsurface.batchnormal3f_bufferoffset = 0;
9851                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9852                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9853                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9854                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9855                                 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);
9856                         // a single autosprite surface can contain multiple sprites...
9857                         for (j = 0;j < batchnumvertices - 3;j += 4)
9858                         {
9859                                 VectorClear(center);
9860                                 for (i = 0;i < 4;i++)
9861                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9862                                 VectorScale(center, 0.25f, center);
9863                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9864                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9865                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9866                                 for (i = 0;i < 4;i++)
9867                                 {
9868                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9869                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9870                                 }
9871                         }
9872                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9873                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9874                         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);
9875                         break;
9876                 case Q3DEFORM_AUTOSPRITE2:
9877                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9878                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9879                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9880                         VectorNormalize(newforward);
9881                         VectorNormalize(newright);
9882                         VectorNormalize(newup);
9883 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9884 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9885 //                      rsurface.batchvertex3f_bufferoffset = 0;
9886                         {
9887                                 const float *v1, *v2;
9888                                 vec3_t start, end;
9889                                 float f, l;
9890                                 struct
9891                                 {
9892                                         float length2;
9893                                         const float *v1;
9894                                         const float *v2;
9895                                 }
9896                                 shortest[2];
9897                                 memset(shortest, 0, sizeof(shortest));
9898                                 // a single autosprite surface can contain multiple sprites...
9899                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9900                                 {
9901                                         VectorClear(center);
9902                                         for (i = 0;i < 4;i++)
9903                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9904                                         VectorScale(center, 0.25f, center);
9905                                         // find the two shortest edges, then use them to define the
9906                                         // axis vectors for rotating around the central axis
9907                                         for (i = 0;i < 6;i++)
9908                                         {
9909                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9910                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9911                                                 l = VectorDistance2(v1, v2);
9912                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9913                                                 if (v1[2] != v2[2])
9914                                                         l += (1.0f / 1024.0f);
9915                                                 if (shortest[0].length2 > l || i == 0)
9916                                                 {
9917                                                         shortest[1] = shortest[0];
9918                                                         shortest[0].length2 = l;
9919                                                         shortest[0].v1 = v1;
9920                                                         shortest[0].v2 = v2;
9921                                                 }
9922                                                 else if (shortest[1].length2 > l || i == 1)
9923                                                 {
9924                                                         shortest[1].length2 = l;
9925                                                         shortest[1].v1 = v1;
9926                                                         shortest[1].v2 = v2;
9927                                                 }
9928                                         }
9929                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9930                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9931                                         // this calculates the right vector from the shortest edge
9932                                         // and the up vector from the edge midpoints
9933                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9934                                         VectorNormalize(right);
9935                                         VectorSubtract(end, start, up);
9936                                         VectorNormalize(up);
9937                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9938                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9939                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9940                                         VectorNegate(forward, forward);
9941                                         VectorReflect(forward, 0, up, forward);
9942                                         VectorNormalize(forward);
9943                                         CrossProduct(up, forward, newright);
9944                                         VectorNormalize(newright);
9945                                         // rotate the quad around the up axis vector, this is made
9946                                         // especially easy by the fact we know the quad is flat,
9947                                         // so we only have to subtract the center position and
9948                                         // measure distance along the right vector, and then
9949                                         // multiply that by the newright vector and add back the
9950                                         // center position
9951                                         // we also need to subtract the old position to undo the
9952                                         // displacement from the center, which we do with a
9953                                         // DotProduct, the subtraction/addition of center is also
9954                                         // optimized into DotProducts here
9955                                         l = DotProduct(right, center);
9956                                         for (i = 0;i < 4;i++)
9957                                         {
9958                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9959                                                 f = DotProduct(right, v1) - l;
9960                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9961                                         }
9962                                 }
9963                         }
9964                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9965                         {
9966 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9967 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9968 //                              rsurface.batchnormal3f_bufferoffset = 0;
9969                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9970                         }
9971                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9972                         {
9973 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9974 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9975 //                              rsurface.batchsvector3f_bufferoffset = 0;
9976 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9977 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9978 //                              rsurface.batchtvector3f_bufferoffset = 0;
9979                                 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);
9980                         }
9981                         break;
9982                 case Q3DEFORM_NORMAL:
9983                         // deform the normals to make reflections wavey
9984                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9985                         rsurface.batchnormal3f_vertexbuffer = NULL;
9986                         rsurface.batchnormal3f_bufferoffset = 0;
9987                         for (j = 0;j < batchnumvertices;j++)
9988                         {
9989                                 float vertex[3];
9990                                 float *normal = rsurface.batchnormal3f + 3*j;
9991                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9992                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9993                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9994                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9995                                 VectorNormalize(normal);
9996                         }
9997                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9998                         {
9999 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10000 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10001 //                              rsurface.batchsvector3f_bufferoffset = 0;
10002 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10003 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10004 //                              rsurface.batchtvector3f_bufferoffset = 0;
10005                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
10006                         }
10007                         break;
10008                 case Q3DEFORM_WAVE:
10009                         // deform vertex array to make wavey water and flags and such
10010                         waveparms[0] = deform->waveparms[0];
10011                         waveparms[1] = deform->waveparms[1];
10012                         waveparms[2] = deform->waveparms[2];
10013                         waveparms[3] = deform->waveparms[3];
10014                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10015                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10016                         // this is how a divisor of vertex influence on deformation
10017                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10018                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10019 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10020 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10021 //                      rsurface.batchvertex3f_bufferoffset = 0;
10022 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10023 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10024 //                      rsurface.batchnormal3f_bufferoffset = 0;
10025                         for (j = 0;j < batchnumvertices;j++)
10026                         {
10027                                 // if the wavefunc depends on time, evaluate it per-vertex
10028                                 if (waveparms[3])
10029                                 {
10030                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10031                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10032                                 }
10033                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10034                         }
10035                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10036                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10037                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10038                         {
10039 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10040 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10041 //                              rsurface.batchsvector3f_bufferoffset = 0;
10042 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10043 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10044 //                              rsurface.batchtvector3f_bufferoffset = 0;
10045                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
10046                         }
10047                         break;
10048                 case Q3DEFORM_BULGE:
10049                         // deform vertex array to make the surface have moving bulges
10050 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10051 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10052 //                      rsurface.batchvertex3f_bufferoffset = 0;
10053 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10054 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10055 //                      rsurface.batchnormal3f_bufferoffset = 0;
10056                         for (j = 0;j < batchnumvertices;j++)
10057                         {
10058                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10059                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10060                         }
10061                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10062                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10063                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10064                         {
10065 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10066 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10067 //                              rsurface.batchsvector3f_bufferoffset = 0;
10068 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10069 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10070 //                              rsurface.batchtvector3f_bufferoffset = 0;
10071                                 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);
10072                         }
10073                         break;
10074                 case Q3DEFORM_MOVE:
10075                         // deform vertex array
10076                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10077                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10078                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10079                         VectorScale(deform->parms, scale, waveparms);
10080 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10081 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10082 //                      rsurface.batchvertex3f_bufferoffset = 0;
10083                         for (j = 0;j < batchnumvertices;j++)
10084                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10085                         break;
10086                 }
10087         }
10088
10089         // generate texcoords based on the chosen texcoord source
10090         switch(rsurface.texture->tcgen.tcgen)
10091         {
10092         default:
10093         case Q3TCGEN_TEXTURE:
10094                 break;
10095         case Q3TCGEN_LIGHTMAP:
10096 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10097 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10098 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10099                 if (rsurface.batchtexcoordlightmap2f)
10100                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10101                 break;
10102         case Q3TCGEN_VECTOR:
10103 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10104 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10105 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10106                 for (j = 0;j < batchnumvertices;j++)
10107                 {
10108                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10109                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10110                 }
10111                 break;
10112         case Q3TCGEN_ENVIRONMENT:
10113                 // make environment reflections using a spheremap
10114                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10115                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10116                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10117                 for (j = 0;j < batchnumvertices;j++)
10118                 {
10119                         // identical to Q3A's method, but executed in worldspace so
10120                         // carried models can be shiny too
10121
10122                         float viewer[3], d, reflected[3], worldreflected[3];
10123
10124                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10125                         // VectorNormalize(viewer);
10126
10127                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10128
10129                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10130                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10131                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10132                         // note: this is proportinal to viewer, so we can normalize later
10133
10134                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10135                         VectorNormalize(worldreflected);
10136
10137                         // note: this sphere map only uses world x and z!
10138                         // so positive and negative y will LOOK THE SAME.
10139                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10140                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10141                 }
10142                 break;
10143         }
10144         // the only tcmod that needs software vertex processing is turbulent, so
10145         // check for it here and apply the changes if needed
10146         // and we only support that as the first one
10147         // (handling a mixture of turbulent and other tcmods would be problematic
10148         //  without punting it entirely to a software path)
10149         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10150         {
10151                 amplitude = rsurface.texture->tcmods[0].parms[1];
10152                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10153 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10154 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10155 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10156                 for (j = 0;j < batchnumvertices;j++)
10157                 {
10158                         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);
10159                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10160                 }
10161         }
10162
10163         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10164         {
10165                 // convert the modified arrays to vertex structs
10166 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10167 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10168 //              rsurface.batchvertexmesh_bufferoffset = 0;
10169                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10170                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10171                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10172                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10173                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10174                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10175                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10176                 {
10177                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10178                         {
10179                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10180                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10181                         }
10182                 }
10183                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10184                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10185                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10186                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10187                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10188                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10189                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10190                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10191                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10192                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10193                 {
10194                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10195                         {
10196                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10197                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10198                         }
10199                 }
10200         }
10201
10202         // upload buffer data for the dynamic batch
10203         if (vid.forcevbo || (r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object))
10204         {
10205                 if (rsurface.batchvertexmesh)
10206                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset, !vid.forcevbo);
10207                 else
10208                 {
10209                         if (rsurface.batchvertex3f)
10210                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset, !vid.forcevbo);
10211                         if (rsurface.batchsvector3f)
10212                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset, !vid.forcevbo);
10213                         if (rsurface.batchtvector3f)
10214                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset, !vid.forcevbo);
10215                         if (rsurface.batchnormal3f)
10216                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset, !vid.forcevbo);
10217                         if (rsurface.batchlightmapcolor4f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10218                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset, !vid.forcevbo);
10219                         if (rsurface.batchtexcoordtexture2f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10220                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset, !vid.forcevbo);
10221                         if (rsurface.batchtexcoordlightmap2f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10222                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset, !vid.forcevbo);
10223                         if (rsurface.batchskeletalindex4ub)
10224                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset, !vid.forcevbo);
10225                         if (rsurface.batchskeletalweight4ub)
10226                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset, !vid.forcevbo);
10227                 }
10228                 if (rsurface.batchelement3s)
10229                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset, !vid.forcevbo);
10230                 else if (rsurface.batchelement3i)
10231                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset, !vid.forcevbo);
10232         }
10233 }
10234
10235 void RSurf_DrawBatch(void)
10236 {
10237         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10238         // through the pipeline, killing it earlier in the pipeline would have
10239         // per-surface overhead rather than per-batch overhead, so it's best to
10240         // reject it here, before it hits glDraw.
10241         if (rsurface.batchnumtriangles == 0)
10242                 return;
10243 #if 0
10244         // batch debugging code
10245         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10246         {
10247                 int i;
10248                 int j;
10249                 int c;
10250                 const int *e;
10251                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10252                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10253                 {
10254                         c = e[i];
10255                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10256                         {
10257                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10258                                 {
10259                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10260                                                 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);
10261                                         break;
10262                                 }
10263                         }
10264                 }
10265         }
10266 #endif
10267         if (rsurface.batchmultidraw)
10268         {
10269                 // issue multiple draws rather than copying index data
10270                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10271                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10272                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10273                 for (i = 0;i < numsurfaces;)
10274                 {
10275                         // combine consecutive surfaces as one draw
10276                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10277                                 if (surfacelist[j] != surfacelist[k] + 1)
10278                                         break;
10279                         firstvertex = surfacelist[i]->num_firstvertex;
10280                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10281                         firsttriangle = surfacelist[i]->num_firsttriangle;
10282                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10283                         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);
10284                         i = j;
10285                 }
10286         }
10287         else
10288         {
10289                 // there is only one consecutive run of index data (may have been combined)
10290                 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);
10291         }
10292 }
10293
10294 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10295 {
10296         // pick the closest matching water plane
10297         int planeindex, vertexindex, bestplaneindex = -1;
10298         float d, bestd;
10299         vec3_t vert;
10300         const float *v;
10301         r_waterstate_waterplane_t *p;
10302         qboolean prepared = false;
10303         bestd = 0;
10304         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10305         {
10306                 if(p->camera_entity != rsurface.texture->camera_entity)
10307                         continue;
10308                 d = 0;
10309                 if(!prepared)
10310                 {
10311                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10312                         prepared = true;
10313                         if(rsurface.batchnumvertices == 0)
10314                                 break;
10315                 }
10316                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10317                 {
10318                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10319                         d += fabs(PlaneDiff(vert, &p->plane));
10320                 }
10321                 if (bestd > d || bestplaneindex < 0)
10322                 {
10323                         bestd = d;
10324                         bestplaneindex = planeindex;
10325                 }
10326         }
10327         return bestplaneindex;
10328         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10329         // this situation though, as it might be better to render single larger
10330         // batches with useless stuff (backface culled for example) than to
10331         // render multiple smaller batches
10332 }
10333
10334 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10335 {
10336         int i;
10337         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10338         rsurface.passcolor4f_vertexbuffer = 0;
10339         rsurface.passcolor4f_bufferoffset = 0;
10340         for (i = 0;i < rsurface.batchnumvertices;i++)
10341                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10342 }
10343
10344 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10345 {
10346         int i;
10347         float f;
10348         const float *v;
10349         const float *c;
10350         float *c2;
10351         if (rsurface.passcolor4f)
10352         {
10353                 // generate color arrays
10354                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10355                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10356                 rsurface.passcolor4f_vertexbuffer = 0;
10357                 rsurface.passcolor4f_bufferoffset = 0;
10358                 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)
10359                 {
10360                         f = RSurf_FogVertex(v);
10361                         c2[0] = c[0] * f;
10362                         c2[1] = c[1] * f;
10363                         c2[2] = c[2] * f;
10364                         c2[3] = c[3];
10365                 }
10366         }
10367         else
10368         {
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, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10373                 {
10374                         f = RSurf_FogVertex(v);
10375                         c2[0] = f;
10376                         c2[1] = f;
10377                         c2[2] = f;
10378                         c2[3] = 1;
10379                 }
10380         }
10381 }
10382
10383 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10384 {
10385         int i;
10386         float f;
10387         const float *v;
10388         const float *c;
10389         float *c2;
10390         if (!rsurface.passcolor4f)
10391                 return;
10392         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10393         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10394         rsurface.passcolor4f_vertexbuffer = 0;
10395         rsurface.passcolor4f_bufferoffset = 0;
10396         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)
10397         {
10398                 f = RSurf_FogVertex(v);
10399                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10400                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10401                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10402                 c2[3] = c[3];
10403         }
10404 }
10405
10406 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10407 {
10408         int i;
10409         const float *c;
10410         float *c2;
10411         if (!rsurface.passcolor4f)
10412                 return;
10413         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10414         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10415         rsurface.passcolor4f_vertexbuffer = 0;
10416         rsurface.passcolor4f_bufferoffset = 0;
10417         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10418         {
10419                 c2[0] = c[0] * r;
10420                 c2[1] = c[1] * g;
10421                 c2[2] = c[2] * b;
10422                 c2[3] = c[3] * a;
10423         }
10424 }
10425
10426 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10427 {
10428         int i;
10429         const float *c;
10430         float *c2;
10431         if (!rsurface.passcolor4f)
10432                 return;
10433         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10434         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10435         rsurface.passcolor4f_vertexbuffer = 0;
10436         rsurface.passcolor4f_bufferoffset = 0;
10437         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10438         {
10439                 c2[0] = c[0] + r_refdef.scene.ambient;
10440                 c2[1] = c[1] + r_refdef.scene.ambient;
10441                 c2[2] = c[2] + r_refdef.scene.ambient;
10442                 c2[3] = c[3];
10443         }
10444 }
10445
10446 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10447 {
10448         // TODO: optimize
10449         rsurface.passcolor4f = NULL;
10450         rsurface.passcolor4f_vertexbuffer = 0;
10451         rsurface.passcolor4f_bufferoffset = 0;
10452         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10453         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10454         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10455         GL_Color(r, g, b, a);
10456         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10457         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10458         R_Mesh_TexMatrix(0, NULL);
10459         RSurf_DrawBatch();
10460 }
10461
10462 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10463 {
10464         // TODO: optimize applyfog && applycolor case
10465         // just apply fog if necessary, and tint the fog color array if necessary
10466         rsurface.passcolor4f = NULL;
10467         rsurface.passcolor4f_vertexbuffer = 0;
10468         rsurface.passcolor4f_bufferoffset = 0;
10469         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10470         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10471         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10472         GL_Color(r, g, b, a);
10473         RSurf_DrawBatch();
10474 }
10475
10476 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10477 {
10478         // TODO: optimize
10479         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10480         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10481         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10482         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10483         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10484         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10485         GL_Color(r, g, b, a);
10486         RSurf_DrawBatch();
10487 }
10488
10489 static void RSurf_DrawBatch_GL11_ClampColor(void)
10490 {
10491         int i;
10492         const float *c1;
10493         float *c2;
10494         if (!rsurface.passcolor4f)
10495                 return;
10496         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10497         {
10498                 c2[0] = bound(0.0f, c1[0], 1.0f);
10499                 c2[1] = bound(0.0f, c1[1], 1.0f);
10500                 c2[2] = bound(0.0f, c1[2], 1.0f);
10501                 c2[3] = bound(0.0f, c1[3], 1.0f);
10502         }
10503 }
10504
10505 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10506 {
10507         int i;
10508         float f;
10509         const float *v;
10510         const float *n;
10511         float *c;
10512         //vec3_t eyedir;
10513
10514         // fake shading
10515         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10516         rsurface.passcolor4f_vertexbuffer = 0;
10517         rsurface.passcolor4f_bufferoffset = 0;
10518         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)
10519         {
10520                 f = -DotProduct(r_refdef.view.forward, n);
10521                 f = max(0, f);
10522                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10523                 f *= r_refdef.lightmapintensity;
10524                 Vector4Set(c, f, f, f, 1);
10525         }
10526 }
10527
10528 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10529 {
10530         RSurf_DrawBatch_GL11_ApplyFakeLight();
10531         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10532         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10533         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10534         GL_Color(r, g, b, a);
10535         RSurf_DrawBatch();
10536 }
10537
10538 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10539 {
10540         int i;
10541         float f;
10542         float alpha;
10543         const float *v;
10544         const float *n;
10545         float *c;
10546         vec3_t ambientcolor;
10547         vec3_t diffusecolor;
10548         vec3_t lightdir;
10549         // TODO: optimize
10550         // model lighting
10551         VectorCopy(rsurface.modellight_lightdir, lightdir);
10552         f = 0.5f * r_refdef.lightmapintensity;
10553         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10554         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10555         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10556         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10557         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10558         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10559         alpha = *a;
10560         if (VectorLength2(diffusecolor) > 0)
10561         {
10562                 // q3-style directional shading
10563                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10564                 rsurface.passcolor4f_vertexbuffer = 0;
10565                 rsurface.passcolor4f_bufferoffset = 0;
10566                 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)
10567                 {
10568                         if ((f = DotProduct(n, lightdir)) > 0)
10569                                 VectorMA(ambientcolor, f, diffusecolor, c);
10570                         else
10571                                 VectorCopy(ambientcolor, c);
10572                         c[3] = alpha;
10573                 }
10574                 *r = 1;
10575                 *g = 1;
10576                 *b = 1;
10577                 *a = 1;
10578                 *applycolor = false;
10579         }
10580         else
10581         {
10582                 *r = ambientcolor[0];
10583                 *g = ambientcolor[1];
10584                 *b = ambientcolor[2];
10585                 rsurface.passcolor4f = NULL;
10586                 rsurface.passcolor4f_vertexbuffer = 0;
10587                 rsurface.passcolor4f_bufferoffset = 0;
10588         }
10589 }
10590
10591 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10592 {
10593         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10594         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10595         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10596         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10597         GL_Color(r, g, b, a);
10598         RSurf_DrawBatch();
10599 }
10600
10601 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10602 {
10603         int i;
10604         float f;
10605         const float *v;
10606         float *c;
10607
10608         // fake shading
10609         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10610         rsurface.passcolor4f_vertexbuffer = 0;
10611         rsurface.passcolor4f_bufferoffset = 0;
10612
10613         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10614         {
10615                 f = 1 - RSurf_FogVertex(v);
10616                 c[0] = r;
10617                 c[1] = g;
10618                 c[2] = b;
10619                 c[3] = f * a;
10620         }
10621 }
10622
10623 void RSurf_SetupDepthAndCulling(void)
10624 {
10625         // submodels are biased to avoid z-fighting with world surfaces that they
10626         // may be exactly overlapping (avoids z-fighting artifacts on certain
10627         // doors and things in Quake maps)
10628         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10629         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10630         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10631         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10632 }
10633
10634 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10635 {
10636         // transparent sky would be ridiculous
10637         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10638                 return;
10639         R_SetupShader_Generic_NoTexture(false, false);
10640         skyrenderlater = true;
10641         RSurf_SetupDepthAndCulling();
10642         GL_DepthMask(true);
10643         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10644         // skymasking on them, and Quake3 never did sky masking (unlike
10645         // software Quake and software Quake2), so disable the sky masking
10646         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10647         // and skymasking also looks very bad when noclipping outside the
10648         // level, so don't use it then either.
10649         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10650         {
10651                 R_Mesh_ResetTextureState();
10652                 if (skyrendermasked)
10653                 {
10654                         R_SetupShader_DepthOrShadow(false, false, false);
10655                         // depth-only (masking)
10656                         GL_ColorMask(0,0,0,0);
10657                         // just to make sure that braindead drivers don't draw
10658                         // anything despite that colormask...
10659                         GL_BlendFunc(GL_ZERO, GL_ONE);
10660                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10661                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10662                 }
10663                 else
10664                 {
10665                         R_SetupShader_Generic_NoTexture(false, false);
10666                         // fog sky
10667                         GL_BlendFunc(GL_ONE, GL_ZERO);
10668                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10669                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10670                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10671                 }
10672                 RSurf_DrawBatch();
10673                 if (skyrendermasked)
10674                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10675         }
10676         R_Mesh_ResetTextureState();
10677         GL_Color(1, 1, 1, 1);
10678 }
10679
10680 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10681 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10682 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10683 {
10684         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10685                 return;
10686         if (prepass)
10687         {
10688                 // render screenspace normalmap to texture
10689                 GL_DepthMask(true);
10690                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10691                 RSurf_DrawBatch();
10692                 return;
10693         }
10694
10695         // bind lightmap texture
10696
10697         // water/refraction/reflection/camera surfaces have to be handled specially
10698         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10699         {
10700                 int start, end, startplaneindex;
10701                 for (start = 0;start < texturenumsurfaces;start = end)
10702                 {
10703                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10704                         if(startplaneindex < 0)
10705                         {
10706                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10707                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10708                                 end = start + 1;
10709                                 continue;
10710                         }
10711                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10712                                 ;
10713                         // now that we have a batch using the same planeindex, render it
10714                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10715                         {
10716                                 // render water or distortion background
10717                                 GL_DepthMask(true);
10718                                 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);
10719                                 RSurf_DrawBatch();
10720                                 // blend surface on top
10721                                 GL_DepthMask(false);
10722                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10723                                 RSurf_DrawBatch();
10724                         }
10725                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10726                         {
10727                                 // render surface with reflection texture as input
10728                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10729                                 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);
10730                                 RSurf_DrawBatch();
10731                         }
10732                 }
10733                 return;
10734         }
10735
10736         // render surface batch normally
10737         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10738         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);
10739         RSurf_DrawBatch();
10740 }
10741
10742 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10743 {
10744         // OpenGL 1.3 path - anything not completely ancient
10745         qboolean applycolor;
10746         qboolean applyfog;
10747         int layerindex;
10748         const texturelayer_t *layer;
10749         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);
10750         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10751
10752         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10753         {
10754                 vec4_t layercolor;
10755                 int layertexrgbscale;
10756                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10757                 {
10758                         if (layerindex == 0)
10759                                 GL_AlphaTest(true);
10760                         else
10761                         {
10762                                 GL_AlphaTest(false);
10763                                 GL_DepthFunc(GL_EQUAL);
10764                         }
10765                 }
10766                 GL_DepthMask(layer->depthmask && writedepth);
10767                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10768                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10769                 {
10770                         layertexrgbscale = 4;
10771                         VectorScale(layer->color, 0.25f, layercolor);
10772                 }
10773                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10774                 {
10775                         layertexrgbscale = 2;
10776                         VectorScale(layer->color, 0.5f, layercolor);
10777                 }
10778                 else
10779                 {
10780                         layertexrgbscale = 1;
10781                         VectorScale(layer->color, 1.0f, layercolor);
10782                 }
10783                 layercolor[3] = layer->color[3];
10784                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10785                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10786                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10787                 switch (layer->type)
10788                 {
10789                 case TEXTURELAYERTYPE_LITTEXTURE:
10790                         // single-pass lightmapped texture with 2x rgbscale
10791                         R_Mesh_TexBind(0, r_texture_white);
10792                         R_Mesh_TexMatrix(0, NULL);
10793                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10794                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10795                         R_Mesh_TexBind(1, layer->texture);
10796                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10797                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10798                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10799                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10800                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10801                         else if (FAKELIGHT_ENABLED)
10802                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10803                         else if (rsurface.uselightmaptexture)
10804                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10805                         else
10806                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10807                         break;
10808                 case TEXTURELAYERTYPE_TEXTURE:
10809                         // singletexture unlit texture with transparency support
10810                         R_Mesh_TexBind(0, layer->texture);
10811                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10812                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10813                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10814                         R_Mesh_TexBind(1, 0);
10815                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10816                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10817                         break;
10818                 case TEXTURELAYERTYPE_FOG:
10819                         // singletexture fogging
10820                         if (layer->texture)
10821                         {
10822                                 R_Mesh_TexBind(0, layer->texture);
10823                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10824                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10825                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10826                         }
10827                         else
10828                         {
10829                                 R_Mesh_TexBind(0, 0);
10830                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10831                         }
10832                         R_Mesh_TexBind(1, 0);
10833                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10834                         // generate a color array for the fog pass
10835                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10836                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10837                         RSurf_DrawBatch();
10838                         break;
10839                 default:
10840                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10841                 }
10842         }
10843         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10844         {
10845                 GL_DepthFunc(GL_LEQUAL);
10846                 GL_AlphaTest(false);
10847         }
10848 }
10849
10850 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10851 {
10852         // OpenGL 1.1 - crusty old voodoo path
10853         qboolean applyfog;
10854         int layerindex;
10855         const texturelayer_t *layer;
10856         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);
10857         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10858
10859         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10860         {
10861                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10862                 {
10863                         if (layerindex == 0)
10864                                 GL_AlphaTest(true);
10865                         else
10866                         {
10867                                 GL_AlphaTest(false);
10868                                 GL_DepthFunc(GL_EQUAL);
10869                         }
10870                 }
10871                 GL_DepthMask(layer->depthmask && writedepth);
10872                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10873                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10874                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10875                 switch (layer->type)
10876                 {
10877                 case TEXTURELAYERTYPE_LITTEXTURE:
10878                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10879                         {
10880                                 // two-pass lit texture with 2x rgbscale
10881                                 // first the lightmap pass
10882                                 R_Mesh_TexBind(0, r_texture_white);
10883                                 R_Mesh_TexMatrix(0, NULL);
10884                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10885                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10886                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10887                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10888                                 else if (FAKELIGHT_ENABLED)
10889                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10890                                 else if (rsurface.uselightmaptexture)
10891                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10892                                 else
10893                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10894                                 // then apply the texture to it
10895                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10896                                 R_Mesh_TexBind(0, layer->texture);
10897                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10898                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10899                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10900                                 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);
10901                         }
10902                         else
10903                         {
10904                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10905                                 R_Mesh_TexBind(0, layer->texture);
10906                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10907                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10908                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10909                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10910                                         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);
10911                                 else if (FAKELIGHT_ENABLED)
10912                                         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);
10913                                 else
10914                                         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);
10915                         }
10916                         break;
10917                 case TEXTURELAYERTYPE_TEXTURE:
10918                         // singletexture unlit texture with transparency support
10919                         R_Mesh_TexBind(0, layer->texture);
10920                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10921                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10922                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10923                         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);
10924                         break;
10925                 case TEXTURELAYERTYPE_FOG:
10926                         // singletexture fogging
10927                         if (layer->texture)
10928                         {
10929                                 R_Mesh_TexBind(0, layer->texture);
10930                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10931                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10932                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10933                         }
10934                         else
10935                         {
10936                                 R_Mesh_TexBind(0, 0);
10937                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10938                         }
10939                         // generate a color array for the fog pass
10940                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10941                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10942                         RSurf_DrawBatch();
10943                         break;
10944                 default:
10945                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10946                 }
10947         }
10948         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10949         {
10950                 GL_DepthFunc(GL_LEQUAL);
10951                 GL_AlphaTest(false);
10952         }
10953 }
10954
10955 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10956 {
10957         int vi;
10958         int j;
10959         r_vertexgeneric_t *batchvertex;
10960         float c[4];
10961
10962 //      R_Mesh_ResetTextureState();
10963         R_SetupShader_Generic_NoTexture(false, false);
10964
10965         if(rsurface.texture && rsurface.texture->currentskinframe)
10966         {
10967                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10968                 c[3] *= rsurface.texture->currentalpha;
10969         }
10970         else
10971         {
10972                 c[0] = 1;
10973                 c[1] = 0;
10974                 c[2] = 1;
10975                 c[3] = 1;
10976         }
10977
10978         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10979         {
10980                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10981                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10982                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10983         }
10984
10985         // brighten it up (as texture value 127 means "unlit")
10986         c[0] *= 2 * r_refdef.view.colorscale;
10987         c[1] *= 2 * r_refdef.view.colorscale;
10988         c[2] *= 2 * r_refdef.view.colorscale;
10989
10990         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10991                 c[3] *= r_wateralpha.value;
10992
10993         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10994         {
10995                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10996                 GL_DepthMask(false);
10997         }
10998         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10999         {
11000                 GL_BlendFunc(GL_ONE, GL_ONE);
11001                 GL_DepthMask(false);
11002         }
11003         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11004         {
11005                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11006                 GL_DepthMask(false);
11007         }
11008         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11009         {
11010                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11011                 GL_DepthMask(false);
11012         }
11013         else
11014         {
11015                 GL_BlendFunc(GL_ONE, GL_ZERO);
11016                 GL_DepthMask(writedepth);
11017         }
11018
11019         if (r_showsurfaces.integer == 3)
11020         {
11021                 rsurface.passcolor4f = NULL;
11022
11023                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11024                 {
11025                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11026
11027                         rsurface.passcolor4f = NULL;
11028                         rsurface.passcolor4f_vertexbuffer = 0;
11029                         rsurface.passcolor4f_bufferoffset = 0;
11030                 }
11031                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11032                 {
11033                         qboolean applycolor = true;
11034                         float one = 1.0;
11035
11036                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11037
11038                         r_refdef.lightmapintensity = 1;
11039                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11040                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11041                 }
11042                 else if (FAKELIGHT_ENABLED)
11043                 {
11044                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11045
11046                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11047                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11048                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11049                 }
11050                 else
11051                 {
11052                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11053
11054                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11055                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11056                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11057                 }
11058
11059                 if(!rsurface.passcolor4f)
11060                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11061
11062                 RSurf_DrawBatch_GL11_ApplyAmbient();
11063                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11064                 if(r_refdef.fogenabled)
11065                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11066                 RSurf_DrawBatch_GL11_ClampColor();
11067
11068                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11069                 R_SetupShader_Generic_NoTexture(false, false);
11070                 RSurf_DrawBatch();
11071         }
11072         else if (!r_refdef.view.showdebug)
11073         {
11074                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11075                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11076                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11077                 {
11078                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11079                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11080                 }
11081                 R_Mesh_PrepareVertices_Generic_Unlock();
11082                 RSurf_DrawBatch();
11083         }
11084         else if (r_showsurfaces.integer == 4)
11085         {
11086                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11087                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11088                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11089                 {
11090                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11091                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11092                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11093                 }
11094                 R_Mesh_PrepareVertices_Generic_Unlock();
11095                 RSurf_DrawBatch();
11096         }
11097         else if (r_showsurfaces.integer == 2)
11098         {
11099                 const int *e;
11100                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11101                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11102                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11103                 {
11104                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11105                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11106                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11107                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11108                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11109                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11110                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11111                 }
11112                 R_Mesh_PrepareVertices_Generic_Unlock();
11113                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11114         }
11115         else
11116         {
11117                 int texturesurfaceindex;
11118                 int k;
11119                 const msurface_t *surface;
11120                 float surfacecolor4f[4];
11121                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11122                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11123                 vi = 0;
11124                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11125                 {
11126                         surface = texturesurfacelist[texturesurfaceindex];
11127                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11128                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11129                         for (j = 0;j < surface->num_vertices;j++)
11130                         {
11131                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11132                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11133                                 vi++;
11134                         }
11135                 }
11136                 R_Mesh_PrepareVertices_Generic_Unlock();
11137                 RSurf_DrawBatch();
11138         }
11139 }
11140
11141 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11142 {
11143         CHECKGLERROR
11144         RSurf_SetupDepthAndCulling();
11145         if (r_showsurfaces.integer)
11146         {
11147                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11148                 return;
11149         }
11150         switch (vid.renderpath)
11151         {
11152         case RENDERPATH_GL20:
11153         case RENDERPATH_D3D9:
11154         case RENDERPATH_D3D10:
11155         case RENDERPATH_D3D11:
11156         case RENDERPATH_SOFT:
11157         case RENDERPATH_GLES2:
11158                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11159                 break;
11160         case RENDERPATH_GL13:
11161         case RENDERPATH_GLES1:
11162                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11163                 break;
11164         case RENDERPATH_GL11:
11165                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11166                 break;
11167         }
11168         CHECKGLERROR
11169 }
11170
11171 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11172 {
11173         CHECKGLERROR
11174         RSurf_SetupDepthAndCulling();
11175         if (r_showsurfaces.integer)
11176         {
11177                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11178                 return;
11179         }
11180         switch (vid.renderpath)
11181         {
11182         case RENDERPATH_GL20:
11183         case RENDERPATH_D3D9:
11184         case RENDERPATH_D3D10:
11185         case RENDERPATH_D3D11:
11186         case RENDERPATH_SOFT:
11187         case RENDERPATH_GLES2:
11188                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11189                 break;
11190         case RENDERPATH_GL13:
11191         case RENDERPATH_GLES1:
11192                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11193                 break;
11194         case RENDERPATH_GL11:
11195                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11196                 break;
11197         }
11198         CHECKGLERROR
11199 }
11200
11201 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11202 {
11203         int i, j;
11204         int texturenumsurfaces, endsurface;
11205         texture_t *texture;
11206         const msurface_t *surface;
11207         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11208
11209         // if the model is static it doesn't matter what value we give for
11210         // wantnormals and wanttangents, so this logic uses only rules applicable
11211         // to a model, knowing that they are meaningless otherwise
11212         if (ent == r_refdef.scene.worldentity)
11213                 RSurf_ActiveWorldEntity();
11214         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11215                 RSurf_ActiveModelEntity(ent, false, false, false);
11216         else
11217         {
11218                 switch (vid.renderpath)
11219                 {
11220                 case RENDERPATH_GL20:
11221                 case RENDERPATH_D3D9:
11222                 case RENDERPATH_D3D10:
11223                 case RENDERPATH_D3D11:
11224                 case RENDERPATH_SOFT:
11225                 case RENDERPATH_GLES2:
11226                         RSurf_ActiveModelEntity(ent, true, true, false);
11227                         break;
11228                 case RENDERPATH_GL11:
11229                 case RENDERPATH_GL13:
11230                 case RENDERPATH_GLES1:
11231                         RSurf_ActiveModelEntity(ent, true, false, false);
11232                         break;
11233                 }
11234         }
11235
11236         if (r_transparentdepthmasking.integer)
11237         {
11238                 qboolean setup = false;
11239                 for (i = 0;i < numsurfaces;i = j)
11240                 {
11241                         j = i + 1;
11242                         surface = rsurface.modelsurfaces + surfacelist[i];
11243                         texture = surface->texture;
11244                         rsurface.texture = R_GetCurrentTexture(texture);
11245                         rsurface.lightmaptexture = NULL;
11246                         rsurface.deluxemaptexture = NULL;
11247                         rsurface.uselightmaptexture = false;
11248                         // scan ahead until we find a different texture
11249                         endsurface = min(i + 1024, numsurfaces);
11250                         texturenumsurfaces = 0;
11251                         texturesurfacelist[texturenumsurfaces++] = surface;
11252                         for (;j < endsurface;j++)
11253                         {
11254                                 surface = rsurface.modelsurfaces + surfacelist[j];
11255                                 if (texture != surface->texture)
11256                                         break;
11257                                 texturesurfacelist[texturenumsurfaces++] = surface;
11258                         }
11259                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11260                                 continue;
11261                         // render the range of surfaces as depth
11262                         if (!setup)
11263                         {
11264                                 setup = true;
11265                                 GL_ColorMask(0,0,0,0);
11266                                 GL_Color(1,1,1,1);
11267                                 GL_DepthTest(true);
11268                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11269                                 GL_DepthMask(true);
11270 //                              R_Mesh_ResetTextureState();
11271                         }
11272                         RSurf_SetupDepthAndCulling();
11273                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11274                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11275                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11276                         RSurf_DrawBatch();
11277                 }
11278                 if (setup)
11279                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11280         }
11281
11282         for (i = 0;i < numsurfaces;i = j)
11283         {
11284                 j = i + 1;
11285                 surface = rsurface.modelsurfaces + surfacelist[i];
11286                 texture = surface->texture;
11287                 rsurface.texture = R_GetCurrentTexture(texture);
11288                 // scan ahead until we find a different texture
11289                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11290                 texturenumsurfaces = 0;
11291                 texturesurfacelist[texturenumsurfaces++] = surface;
11292                 if(FAKELIGHT_ENABLED)
11293                 {
11294                         rsurface.lightmaptexture = NULL;
11295                         rsurface.deluxemaptexture = NULL;
11296                         rsurface.uselightmaptexture = false;
11297                         for (;j < endsurface;j++)
11298                         {
11299                                 surface = rsurface.modelsurfaces + surfacelist[j];
11300                                 if (texture != surface->texture)
11301                                         break;
11302                                 texturesurfacelist[texturenumsurfaces++] = surface;
11303                         }
11304                 }
11305                 else
11306                 {
11307                         rsurface.lightmaptexture = surface->lightmaptexture;
11308                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11309                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11310                         for (;j < endsurface;j++)
11311                         {
11312                                 surface = rsurface.modelsurfaces + surfacelist[j];
11313                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11314                                         break;
11315                                 texturesurfacelist[texturenumsurfaces++] = surface;
11316                         }
11317                 }
11318                 // render the range of surfaces
11319                 if (ent == r_refdef.scene.worldentity)
11320                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11321                 else
11322                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11323         }
11324         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11325 }
11326
11327 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11328 {
11329         // transparent surfaces get pushed off into the transparent queue
11330         int surfacelistindex;
11331         const msurface_t *surface;
11332         vec3_t tempcenter, center;
11333         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11334         {
11335                 surface = texturesurfacelist[surfacelistindex];
11336                 if (r_transparent_sortsurfacesbynearest.integer)
11337                 {
11338                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11339                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11340                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11341                 }
11342                 else
11343                 {
11344                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11345                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11346                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11347                 }
11348                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11349                 if (rsurface.entity->transparent_offset) // transparent offset
11350                 {
11351                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11352                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11353                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11354                 }
11355                 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);
11356         }
11357 }
11358
11359 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11360 {
11361         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11362                 return;
11363         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11364                 return;
11365         RSurf_SetupDepthAndCulling();
11366         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11367         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11368         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11369         RSurf_DrawBatch();
11370 }
11371
11372 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11373 {
11374         CHECKGLERROR
11375         if (depthonly)
11376                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11377         else if (prepass)
11378         {
11379                 if (!rsurface.texture->currentnumlayers)
11380                         return;
11381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11382                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11383                 else
11384                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11385         }
11386         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11387                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11388         else if (!rsurface.texture->currentnumlayers)
11389                 return;
11390         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11391         {
11392                 // in the deferred case, transparent surfaces were queued during prepass
11393                 if (!r_shadow_usingdeferredprepass)
11394                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11395         }
11396         else
11397         {
11398                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11399                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11400         }
11401         CHECKGLERROR
11402 }
11403
11404 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11405 {
11406         int i, j;
11407         texture_t *texture;
11408         R_FrameData_SetMark();
11409         // break the surface list down into batches by texture and use of lightmapping
11410         for (i = 0;i < numsurfaces;i = j)
11411         {
11412                 j = i + 1;
11413                 // texture is the base texture pointer, rsurface.texture is the
11414                 // current frame/skin the texture is directing us to use (for example
11415                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11416                 // use skin 1 instead)
11417                 texture = surfacelist[i]->texture;
11418                 rsurface.texture = R_GetCurrentTexture(texture);
11419                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11420                 {
11421                         // if this texture is not the kind we want, skip ahead to the next one
11422                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11423                                 ;
11424                         continue;
11425                 }
11426                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11427                 {
11428                         rsurface.lightmaptexture = NULL;
11429                         rsurface.deluxemaptexture = NULL;
11430                         rsurface.uselightmaptexture = false;
11431                         // simply scan ahead until we find a different texture or lightmap state
11432                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11433                                 ;
11434                 }
11435                 else
11436                 {
11437                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11438                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11439                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11440                         // simply scan ahead until we find a different texture or lightmap state
11441                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11442                                 ;
11443                 }
11444                 // render the range of surfaces
11445                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11446         }
11447         R_FrameData_ReturnToMark();
11448 }
11449
11450 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11451 {
11452         CHECKGLERROR
11453         if (depthonly)
11454                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11455         else if (prepass)
11456         {
11457                 if (!rsurface.texture->currentnumlayers)
11458                         return;
11459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11460                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11461                 else
11462                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11463         }
11464         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11465                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11466         else if (!rsurface.texture->currentnumlayers)
11467                 return;
11468         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11469         {
11470                 // in the deferred case, transparent surfaces were queued during prepass
11471                 if (!r_shadow_usingdeferredprepass)
11472                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11473         }
11474         else
11475         {
11476                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11477                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11478         }
11479         CHECKGLERROR
11480 }
11481
11482 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11483 {
11484         int i, j;
11485         texture_t *texture;
11486         R_FrameData_SetMark();
11487         // break the surface list down into batches by texture and use of lightmapping
11488         for (i = 0;i < numsurfaces;i = j)
11489         {
11490                 j = i + 1;
11491                 // texture is the base texture pointer, rsurface.texture is the
11492                 // current frame/skin the texture is directing us to use (for example
11493                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11494                 // use skin 1 instead)
11495                 texture = surfacelist[i]->texture;
11496                 rsurface.texture = R_GetCurrentTexture(texture);
11497                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11498                 {
11499                         // if this texture is not the kind we want, skip ahead to the next one
11500                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11501                                 ;
11502                         continue;
11503                 }
11504                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11505                 {
11506                         rsurface.lightmaptexture = NULL;
11507                         rsurface.deluxemaptexture = NULL;
11508                         rsurface.uselightmaptexture = false;
11509                         // simply scan ahead until we find a different texture or lightmap state
11510                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11511                                 ;
11512                 }
11513                 else
11514                 {
11515                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11516                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11517                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11518                         // simply scan ahead until we find a different texture or lightmap state
11519                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11520                                 ;
11521                 }
11522                 // render the range of surfaces
11523                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11524         }
11525         R_FrameData_ReturnToMark();
11526 }
11527
11528 float locboxvertex3f[6*4*3] =
11529 {
11530         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11531         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11532         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11533         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11534         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11535         1,0,0, 0,0,0, 0,1,0, 1,1,0
11536 };
11537
11538 unsigned short locboxelements[6*2*3] =
11539 {
11540          0, 1, 2, 0, 2, 3,
11541          4, 5, 6, 4, 6, 7,
11542          8, 9,10, 8,10,11,
11543         12,13,14, 12,14,15,
11544         16,17,18, 16,18,19,
11545         20,21,22, 20,22,23
11546 };
11547
11548 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11549 {
11550         int i, j;
11551         cl_locnode_t *loc = (cl_locnode_t *)ent;
11552         vec3_t mins, size;
11553         float vertex3f[6*4*3];
11554         CHECKGLERROR
11555         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11556         GL_DepthMask(false);
11557         GL_DepthRange(0, 1);
11558         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11559         GL_DepthTest(true);
11560         GL_CullFace(GL_NONE);
11561         R_EntityMatrix(&identitymatrix);
11562
11563 //      R_Mesh_ResetTextureState();
11564
11565         i = surfacelist[0];
11566         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11567                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11568                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11569                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11570
11571         if (VectorCompare(loc->mins, loc->maxs))
11572         {
11573                 VectorSet(size, 2, 2, 2);
11574                 VectorMA(loc->mins, -0.5f, size, mins);
11575         }
11576         else
11577         {
11578                 VectorCopy(loc->mins, mins);
11579                 VectorSubtract(loc->maxs, loc->mins, size);
11580         }
11581
11582         for (i = 0;i < 6*4*3;)
11583                 for (j = 0;j < 3;j++, i++)
11584                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11585
11586         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11587         R_SetupShader_Generic_NoTexture(false, false);
11588         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11589 }
11590
11591 void R_DrawLocs(void)
11592 {
11593         int index;
11594         cl_locnode_t *loc, *nearestloc;
11595         vec3_t center;
11596         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11597         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11598         {
11599                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11600                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11601         }
11602 }
11603
11604 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11605 {
11606         if (decalsystem->decals)
11607                 Mem_Free(decalsystem->decals);
11608         memset(decalsystem, 0, sizeof(*decalsystem));
11609 }
11610
11611 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, int decalsequence)
11612 {
11613         tridecal_t *decal;
11614         tridecal_t *decals;
11615         int i;
11616
11617         // expand or initialize the system
11618         if (decalsystem->maxdecals <= decalsystem->numdecals)
11619         {
11620                 decalsystem_t old = *decalsystem;
11621                 qboolean useshortelements;
11622                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11623                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11624                 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)));
11625                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11626                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11627                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11628                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11629                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11630                 if (decalsystem->numdecals)
11631                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11632                 if (old.decals)
11633                         Mem_Free(old.decals);
11634                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11635                         decalsystem->element3i[i] = i;
11636                 if (useshortelements)
11637                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11638                                 decalsystem->element3s[i] = i;
11639         }
11640
11641         // grab a decal and search for another free slot for the next one
11642         decals = decalsystem->decals;
11643         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11644         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11645                 ;
11646         decalsystem->freedecal = i;
11647         if (decalsystem->numdecals <= i)
11648                 decalsystem->numdecals = i + 1;
11649
11650         // initialize the decal
11651         decal->lived = 0;
11652         decal->triangleindex = triangleindex;
11653         decal->surfaceindex = surfaceindex;
11654         decal->decalsequence = decalsequence;
11655         decal->color4f[0][0] = c0[0];
11656         decal->color4f[0][1] = c0[1];
11657         decal->color4f[0][2] = c0[2];
11658         decal->color4f[0][3] = 1;
11659         decal->color4f[1][0] = c1[0];
11660         decal->color4f[1][1] = c1[1];
11661         decal->color4f[1][2] = c1[2];
11662         decal->color4f[1][3] = 1;
11663         decal->color4f[2][0] = c2[0];
11664         decal->color4f[2][1] = c2[1];
11665         decal->color4f[2][2] = c2[2];
11666         decal->color4f[2][3] = 1;
11667         decal->vertex3f[0][0] = v0[0];
11668         decal->vertex3f[0][1] = v0[1];
11669         decal->vertex3f[0][2] = v0[2];
11670         decal->vertex3f[1][0] = v1[0];
11671         decal->vertex3f[1][1] = v1[1];
11672         decal->vertex3f[1][2] = v1[2];
11673         decal->vertex3f[2][0] = v2[0];
11674         decal->vertex3f[2][1] = v2[1];
11675         decal->vertex3f[2][2] = v2[2];
11676         decal->texcoord2f[0][0] = t0[0];
11677         decal->texcoord2f[0][1] = t0[1];
11678         decal->texcoord2f[1][0] = t1[0];
11679         decal->texcoord2f[1][1] = t1[1];
11680         decal->texcoord2f[2][0] = t2[0];
11681         decal->texcoord2f[2][1] = t2[1];
11682         TriangleNormal(v0, v1, v2, decal->plane);
11683         VectorNormalize(decal->plane);
11684         decal->plane[3] = DotProduct(v0, decal->plane);
11685 }
11686
11687 extern cvar_t cl_decals_bias;
11688 extern cvar_t cl_decals_models;
11689 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11690 // baseparms, parms, temps
11691 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11692 {
11693         int cornerindex;
11694         int index;
11695         float v[9][3];
11696         const float *vertex3f;
11697         const float *normal3f;
11698         int numpoints;
11699         float points[2][9][3];
11700         float temp[3];
11701         float tc[9][2];
11702         float f;
11703         float c[9][4];
11704         const int *e;
11705
11706         e = rsurface.modelelement3i + 3*triangleindex;
11707
11708         vertex3f = rsurface.modelvertex3f;
11709         normal3f = rsurface.modelnormal3f;
11710
11711         if (normal3f)
11712         {
11713                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11714                 {
11715                         index = 3*e[cornerindex];
11716                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11717                 }
11718         }
11719         else
11720         {
11721                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11722                 {
11723                         index = 3*e[cornerindex];
11724                         VectorCopy(vertex3f + index, v[cornerindex]);
11725                 }
11726         }
11727
11728         // cull backfaces
11729         //TriangleNormal(v[0], v[1], v[2], normal);
11730         //if (DotProduct(normal, localnormal) < 0.0f)
11731         //      continue;
11732         // clip by each of the box planes formed from the projection matrix
11733         // if anything survives, we emit the decal
11734         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]);
11735         if (numpoints < 3)
11736                 return;
11737         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]);
11738         if (numpoints < 3)
11739                 return;
11740         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]);
11741         if (numpoints < 3)
11742                 return;
11743         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]);
11744         if (numpoints < 3)
11745                 return;
11746         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]);
11747         if (numpoints < 3)
11748                 return;
11749         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]);
11750         if (numpoints < 3)
11751                 return;
11752         // some part of the triangle survived, so we have to accept it...
11753         if (dynamic)
11754         {
11755                 // dynamic always uses the original triangle
11756                 numpoints = 3;
11757                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11758                 {
11759                         index = 3*e[cornerindex];
11760                         VectorCopy(vertex3f + index, v[cornerindex]);
11761                 }
11762         }
11763         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11764         {
11765                 // convert vertex positions to texcoords
11766                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11767                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11768                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11769                 // calculate distance fade from the projection origin
11770                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11771                 f = bound(0.0f, f, 1.0f);
11772                 c[cornerindex][0] = r * f;
11773                 c[cornerindex][1] = g * f;
11774                 c[cornerindex][2] = b * f;
11775                 c[cornerindex][3] = 1.0f;
11776                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11777         }
11778         if (dynamic)
11779                 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);
11780         else
11781                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11782                         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);
11783 }
11784 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, int decalsequence)
11785 {
11786         matrix4x4_t projection;
11787         decalsystem_t *decalsystem;
11788         qboolean dynamic;
11789         dp_model_t *model;
11790         const msurface_t *surface;
11791         const msurface_t *surfaces;
11792         const int *surfacelist;
11793         const texture_t *texture;
11794         int numtriangles;
11795         int numsurfacelist;
11796         int surfacelistindex;
11797         int surfaceindex;
11798         int triangleindex;
11799         float localorigin[3];
11800         float localnormal[3];
11801         float localmins[3];
11802         float localmaxs[3];
11803         float localsize;
11804         //float normal[3];
11805         float planes[6][4];
11806         float angles[3];
11807         bih_t *bih;
11808         int bih_triangles_count;
11809         int bih_triangles[256];
11810         int bih_surfaces[256];
11811
11812         decalsystem = &ent->decalsystem;
11813         model = ent->model;
11814         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11815         {
11816                 R_DecalSystem_Reset(&ent->decalsystem);
11817                 return;
11818         }
11819
11820         if (!model->brush.data_leafs && !cl_decals_models.integer)
11821         {
11822                 if (decalsystem->model)
11823                         R_DecalSystem_Reset(decalsystem);
11824                 return;
11825         }
11826
11827         if (decalsystem->model != model)
11828                 R_DecalSystem_Reset(decalsystem);
11829         decalsystem->model = model;
11830
11831         RSurf_ActiveModelEntity(ent, true, false, false);
11832
11833         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11834         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11835         VectorNormalize(localnormal);
11836         localsize = worldsize*rsurface.inversematrixscale;
11837         localmins[0] = localorigin[0] - localsize;
11838         localmins[1] = localorigin[1] - localsize;
11839         localmins[2] = localorigin[2] - localsize;
11840         localmaxs[0] = localorigin[0] + localsize;
11841         localmaxs[1] = localorigin[1] + localsize;
11842         localmaxs[2] = localorigin[2] + localsize;
11843
11844         //VectorCopy(localnormal, planes[4]);
11845         //VectorVectors(planes[4], planes[2], planes[0]);
11846         AnglesFromVectors(angles, localnormal, NULL, false);
11847         AngleVectors(angles, planes[0], planes[2], planes[4]);
11848         VectorNegate(planes[0], planes[1]);
11849         VectorNegate(planes[2], planes[3]);
11850         VectorNegate(planes[4], planes[5]);
11851         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11852         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11853         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11854         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11855         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11856         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11857
11858 #if 1
11859 // works
11860 {
11861         matrix4x4_t forwardprojection;
11862         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11863         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11864 }
11865 #else
11866 // broken
11867 {
11868         float projectionvector[4][3];
11869         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11870         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11871         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11872         projectionvector[0][0] = planes[0][0] * ilocalsize;
11873         projectionvector[0][1] = planes[1][0] * ilocalsize;
11874         projectionvector[0][2] = planes[2][0] * ilocalsize;
11875         projectionvector[1][0] = planes[0][1] * ilocalsize;
11876         projectionvector[1][1] = planes[1][1] * ilocalsize;
11877         projectionvector[1][2] = planes[2][1] * ilocalsize;
11878         projectionvector[2][0] = planes[0][2] * ilocalsize;
11879         projectionvector[2][1] = planes[1][2] * ilocalsize;
11880         projectionvector[2][2] = planes[2][2] * ilocalsize;
11881         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11882         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11883         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11884         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11885 }
11886 #endif
11887
11888         dynamic = model->surfmesh.isanimated;
11889         numsurfacelist = model->nummodelsurfaces;
11890         surfacelist = model->sortedmodelsurfaces;
11891         surfaces = model->data_surfaces;
11892
11893         bih = NULL;
11894         bih_triangles_count = -1;
11895         if(!dynamic)
11896         {
11897                 if(model->render_bih.numleafs)
11898                         bih = &model->render_bih;
11899                 else if(model->collision_bih.numleafs)
11900                         bih = &model->collision_bih;
11901         }
11902         if(bih)
11903                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11904         if(bih_triangles_count == 0)
11905                 return;
11906         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11907                 return;
11908         if(bih_triangles_count > 0)
11909         {
11910                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11911                 {
11912                         surfaceindex = bih_surfaces[triangleindex];
11913                         surface = surfaces + surfaceindex;
11914                         texture = surface->texture;
11915                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11916                                 continue;
11917                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11918                                 continue;
11919                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11920                 }
11921         }
11922         else
11923         {
11924                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11925                 {
11926                         surfaceindex = surfacelist[surfacelistindex];
11927                         surface = surfaces + surfaceindex;
11928                         // check cull box first because it rejects more than any other check
11929                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11930                                 continue;
11931                         // skip transparent surfaces
11932                         texture = surface->texture;
11933                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11934                                 continue;
11935                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11936                                 continue;
11937                         numtriangles = surface->num_triangles;
11938                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11939                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11940                 }
11941         }
11942 }
11943
11944 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11945 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, int decalsequence)
11946 {
11947         int renderentityindex;
11948         float worldmins[3];
11949         float worldmaxs[3];
11950         entity_render_t *ent;
11951
11952         if (!cl_decals_newsystem.integer)
11953                 return;
11954
11955         worldmins[0] = worldorigin[0] - worldsize;
11956         worldmins[1] = worldorigin[1] - worldsize;
11957         worldmins[2] = worldorigin[2] - worldsize;
11958         worldmaxs[0] = worldorigin[0] + worldsize;
11959         worldmaxs[1] = worldorigin[1] + worldsize;
11960         worldmaxs[2] = worldorigin[2] + worldsize;
11961
11962         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11963
11964         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11965         {
11966                 ent = r_refdef.scene.entities[renderentityindex];
11967                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11968                         continue;
11969
11970                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11971         }
11972 }
11973
11974 typedef struct r_decalsystem_splatqueue_s
11975 {
11976         vec3_t worldorigin;
11977         vec3_t worldnormal;
11978         float color[4];
11979         float tcrange[4];
11980         float worldsize;
11981         int decalsequence;
11982 }
11983 r_decalsystem_splatqueue_t;
11984
11985 int r_decalsystem_numqueued = 0;
11986 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11987
11988 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)
11989 {
11990         r_decalsystem_splatqueue_t *queue;
11991
11992         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11993                 return;
11994
11995         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11996         VectorCopy(worldorigin, queue->worldorigin);
11997         VectorCopy(worldnormal, queue->worldnormal);
11998         Vector4Set(queue->color, r, g, b, a);
11999         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12000         queue->worldsize = worldsize;
12001         queue->decalsequence = cl.decalsequence++;
12002 }
12003
12004 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12005 {
12006         int i;
12007         r_decalsystem_splatqueue_t *queue;
12008
12009         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12010                 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);
12011         r_decalsystem_numqueued = 0;
12012 }
12013
12014 extern cvar_t cl_decals_max;
12015 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12016 {
12017         int i;
12018         decalsystem_t *decalsystem = &ent->decalsystem;
12019         int numdecals;
12020         int killsequence;
12021         tridecal_t *decal;
12022         float frametime;
12023         float lifetime;
12024
12025         if (!decalsystem->numdecals)
12026                 return;
12027
12028         if (r_showsurfaces.integer)
12029                 return;
12030
12031         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12032         {
12033                 R_DecalSystem_Reset(decalsystem);
12034                 return;
12035         }
12036
12037         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12038         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12039
12040         if (decalsystem->lastupdatetime)
12041                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12042         else
12043                 frametime = 0;
12044         decalsystem->lastupdatetime = r_refdef.scene.time;
12045         numdecals = decalsystem->numdecals;
12046
12047         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12048         {
12049                 if (decal->color4f[0][3])
12050                 {
12051                         decal->lived += frametime;
12052                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12053                         {
12054                                 memset(decal, 0, sizeof(*decal));
12055                                 if (decalsystem->freedecal > i)
12056                                         decalsystem->freedecal = i;
12057                         }
12058                 }
12059         }
12060         decal = decalsystem->decals;
12061         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12062                 numdecals--;
12063
12064         // collapse the array by shuffling the tail decals into the gaps
12065         for (;;)
12066         {
12067                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12068                         decalsystem->freedecal++;
12069                 if (decalsystem->freedecal == numdecals)
12070                         break;
12071                 decal[decalsystem->freedecal] = decal[--numdecals];
12072         }
12073
12074         decalsystem->numdecals = numdecals;
12075
12076         if (numdecals <= 0)
12077         {
12078                 // if there are no decals left, reset decalsystem
12079                 R_DecalSystem_Reset(decalsystem);
12080         }
12081 }
12082
12083 extern skinframe_t *decalskinframe;
12084 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12085 {
12086         int i;
12087         decalsystem_t *decalsystem = &ent->decalsystem;
12088         int numdecals;
12089         tridecal_t *decal;
12090         float faderate;
12091         float alpha;
12092         float *v3f;
12093         float *c4f;
12094         float *t2f;
12095         const int *e;
12096         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12097         int numtris = 0;
12098
12099         numdecals = decalsystem->numdecals;
12100         if (!numdecals)
12101                 return;
12102
12103         if (r_showsurfaces.integer)
12104                 return;
12105
12106         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12107         {
12108                 R_DecalSystem_Reset(decalsystem);
12109                 return;
12110         }
12111
12112         // if the model is static it doesn't matter what value we give for
12113         // wantnormals and wanttangents, so this logic uses only rules applicable
12114         // to a model, knowing that they are meaningless otherwise
12115         if (ent == r_refdef.scene.worldentity)
12116                 RSurf_ActiveWorldEntity();
12117         else
12118                 RSurf_ActiveModelEntity(ent, false, false, false);
12119
12120         decalsystem->lastupdatetime = r_refdef.scene.time;
12121
12122         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12123
12124         // update vertex positions for animated models
12125         v3f = decalsystem->vertex3f;
12126         c4f = decalsystem->color4f;
12127         t2f = decalsystem->texcoord2f;
12128         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12129         {
12130                 if (!decal->color4f[0][3])
12131                         continue;
12132
12133                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12134                         continue;
12135
12136                 // skip backfaces
12137                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12138                         continue;
12139
12140                 // update color values for fading decals
12141                 if (decal->lived >= cl_decals_time.value)
12142                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12143                 else
12144                         alpha = 1.0f;
12145
12146                 c4f[ 0] = decal->color4f[0][0] * alpha;
12147                 c4f[ 1] = decal->color4f[0][1] * alpha;
12148                 c4f[ 2] = decal->color4f[0][2] * alpha;
12149                 c4f[ 3] = 1;
12150                 c4f[ 4] = decal->color4f[1][0] * alpha;
12151                 c4f[ 5] = decal->color4f[1][1] * alpha;
12152                 c4f[ 6] = decal->color4f[1][2] * alpha;
12153                 c4f[ 7] = 1;
12154                 c4f[ 8] = decal->color4f[2][0] * alpha;
12155                 c4f[ 9] = decal->color4f[2][1] * alpha;
12156                 c4f[10] = decal->color4f[2][2] * alpha;
12157                 c4f[11] = 1;
12158
12159                 t2f[0] = decal->texcoord2f[0][0];
12160                 t2f[1] = decal->texcoord2f[0][1];
12161                 t2f[2] = decal->texcoord2f[1][0];
12162                 t2f[3] = decal->texcoord2f[1][1];
12163                 t2f[4] = decal->texcoord2f[2][0];
12164                 t2f[5] = decal->texcoord2f[2][1];
12165
12166                 // update vertex positions for animated models
12167                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12168                 {
12169                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12170                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12171                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12172                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12173                 }
12174                 else
12175                 {
12176                         VectorCopy(decal->vertex3f[0], v3f);
12177                         VectorCopy(decal->vertex3f[1], v3f + 3);
12178                         VectorCopy(decal->vertex3f[2], v3f + 6);
12179                 }
12180
12181                 if (r_refdef.fogenabled)
12182                 {
12183                         alpha = RSurf_FogVertex(v3f);
12184                         VectorScale(c4f, alpha, c4f);
12185                         alpha = RSurf_FogVertex(v3f + 3);
12186                         VectorScale(c4f + 4, alpha, c4f + 4);
12187                         alpha = RSurf_FogVertex(v3f + 6);
12188                         VectorScale(c4f + 8, alpha, c4f + 8);
12189                 }
12190
12191                 v3f += 9;
12192                 c4f += 12;
12193                 t2f += 6;
12194                 numtris++;
12195         }
12196
12197         if (numtris > 0)
12198         {
12199                 r_refdef.stats[r_stat_drawndecals] += numtris;
12200
12201                 // now render the decals all at once
12202                 // (this assumes they all use one particle font texture!)
12203                 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);
12204 //              R_Mesh_ResetTextureState();
12205                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12206                 GL_DepthMask(false);
12207                 GL_DepthRange(0, 1);
12208                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12209                 GL_DepthTest(true);
12210                 GL_CullFace(GL_NONE);
12211                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12212                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12213                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12214         }
12215 }
12216
12217 static void R_DrawModelDecals(void)
12218 {
12219         int i, numdecals;
12220
12221         // fade faster when there are too many decals
12222         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12223         for (i = 0;i < r_refdef.scene.numentities;i++)
12224                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12225
12226         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12227         for (i = 0;i < r_refdef.scene.numentities;i++)
12228                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12229                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12230
12231         R_DecalSystem_ApplySplatEntitiesQueue();
12232
12233         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12234         for (i = 0;i < r_refdef.scene.numentities;i++)
12235                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12236
12237         r_refdef.stats[r_stat_totaldecals] += numdecals;
12238
12239         if (r_showsurfaces.integer)
12240                 return;
12241
12242         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12243
12244         for (i = 0;i < r_refdef.scene.numentities;i++)
12245         {
12246                 if (!r_refdef.viewcache.entityvisible[i])
12247                         continue;
12248                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12249                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12250         }
12251 }
12252
12253 extern cvar_t mod_collision_bih;
12254 static void R_DrawDebugModel(void)
12255 {
12256         entity_render_t *ent = rsurface.entity;
12257         int i, j, k, l, flagsmask;
12258         const msurface_t *surface;
12259         dp_model_t *model = ent->model;
12260         vec3_t v;
12261
12262         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12263                 return;
12264
12265         if (r_showoverdraw.value > 0)
12266         {
12267                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12268                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12269                 R_SetupShader_Generic_NoTexture(false, false);
12270                 GL_DepthTest(false);
12271                 GL_DepthMask(false);
12272                 GL_DepthRange(0, 1);
12273                 GL_BlendFunc(GL_ONE, GL_ONE);
12274                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12275                 {
12276                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12277                                 continue;
12278                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12279                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12280                         {
12281                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12282                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12283                                 if (!rsurface.texture->currentlayers->depthmask)
12284                                         GL_Color(c, 0, 0, 1.0f);
12285                                 else if (ent == r_refdef.scene.worldentity)
12286                                         GL_Color(c, c, c, 1.0f);
12287                                 else
12288                                         GL_Color(0, c, 0, 1.0f);
12289                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12290                                 RSurf_DrawBatch();
12291                         }
12292                 }
12293                 rsurface.texture = NULL;
12294         }
12295
12296         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12297
12298 //      R_Mesh_ResetTextureState();
12299         R_SetupShader_Generic_NoTexture(false, false);
12300         GL_DepthRange(0, 1);
12301         GL_DepthTest(!r_showdisabledepthtest.integer);
12302         GL_DepthMask(false);
12303         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12304
12305         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12306         {
12307                 int triangleindex;
12308                 int bihleafindex;
12309                 qboolean cullbox = false;
12310                 const q3mbrush_t *brush;
12311                 const bih_t *bih = &model->collision_bih;
12312                 const bih_leaf_t *bihleaf;
12313                 float vertex3f[3][3];
12314                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12315                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12316                 {
12317                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12318                                 continue;
12319                         switch (bihleaf->type)
12320                         {
12321                         case BIH_BRUSH:
12322                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12323                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12324                                 {
12325                                         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);
12326                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12327                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12328                                 }
12329                                 break;
12330                         case BIH_COLLISIONTRIANGLE:
12331                                 triangleindex = bihleaf->itemindex;
12332                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12333                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12334                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12335                                 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);
12336                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12337                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12338                                 break;
12339                         case BIH_RENDERTRIANGLE:
12340                                 triangleindex = bihleaf->itemindex;
12341                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12342                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12343                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12344                                 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);
12345                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12346                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12347                                 break;
12348                         }
12349                 }
12350         }
12351
12352         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12353
12354 #ifndef USE_GLES2
12355         if (r_showtris.integer && qglPolygonMode)
12356         {
12357                 if (r_showdisabledepthtest.integer)
12358                 {
12359                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12360                         GL_DepthMask(false);
12361                 }
12362                 else
12363                 {
12364                         GL_BlendFunc(GL_ONE, GL_ZERO);
12365                         GL_DepthMask(true);
12366                 }
12367                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12368                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12369                 {
12370                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12371                                 continue;
12372                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12373                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12374                         {
12375                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12376                                 if (!rsurface.texture->currentlayers->depthmask)
12377                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12378                                 else if (ent == r_refdef.scene.worldentity)
12379                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12380                                 else
12381                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12382                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12383                                 RSurf_DrawBatch();
12384                         }
12385                 }
12386                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12387                 rsurface.texture = NULL;
12388         }
12389
12390         if (r_shownormals.value != 0 && qglBegin)
12391         {
12392                 if (r_showdisabledepthtest.integer)
12393                 {
12394                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12395                         GL_DepthMask(false);
12396                 }
12397                 else
12398                 {
12399                         GL_BlendFunc(GL_ONE, GL_ZERO);
12400                         GL_DepthMask(true);
12401                 }
12402                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12403                 {
12404                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12405                                 continue;
12406                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12407                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12408                         {
12409                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12410                                 qglBegin(GL_LINES);
12411                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12412                                 {
12413                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12414                                         {
12415                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12416                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12417                                                 qglVertex3f(v[0], v[1], v[2]);
12418                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12419                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12420                                                 qglVertex3f(v[0], v[1], v[2]);
12421                                         }
12422                                 }
12423                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12424                                 {
12425                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12426                                         {
12427                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12428                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12429                                                 qglVertex3f(v[0], v[1], v[2]);
12430                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12431                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12432                                                 qglVertex3f(v[0], v[1], v[2]);
12433                                         }
12434                                 }
12435                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12436                                 {
12437                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12438                                         {
12439                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12440                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12441                                                 qglVertex3f(v[0], v[1], v[2]);
12442                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12443                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12444                                                 qglVertex3f(v[0], v[1], v[2]);
12445                                         }
12446                                 }
12447                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12448                                 {
12449                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12450                                         {
12451                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12452                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12453                                                 qglVertex3f(v[0], v[1], v[2]);
12454                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12455                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12456                                                 qglVertex3f(v[0], v[1], v[2]);
12457                                         }
12458                                 }
12459                                 qglEnd();
12460                                 CHECKGLERROR
12461                         }
12462                 }
12463                 rsurface.texture = NULL;
12464         }
12465 #endif
12466 }
12467
12468 int r_maxsurfacelist = 0;
12469 const msurface_t **r_surfacelist = NULL;
12470 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12471 {
12472         int i, j, endj, flagsmask;
12473         dp_model_t *model = r_refdef.scene.worldmodel;
12474         msurface_t *surfaces;
12475         unsigned char *update;
12476         int numsurfacelist = 0;
12477         if (model == NULL)
12478                 return;
12479
12480         if (r_maxsurfacelist < model->num_surfaces)
12481         {
12482                 r_maxsurfacelist = model->num_surfaces;
12483                 if (r_surfacelist)
12484                         Mem_Free((msurface_t**)r_surfacelist);
12485                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12486         }
12487
12488         RSurf_ActiveWorldEntity();
12489
12490         surfaces = model->data_surfaces;
12491         update = model->brushq1.lightmapupdateflags;
12492
12493         // update light styles on this submodel
12494         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12495         {
12496                 model_brush_lightstyleinfo_t *style;
12497                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12498                 {
12499                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12500                         {
12501                                 int *list = style->surfacelist;
12502                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12503                                 for (j = 0;j < style->numsurfaces;j++)
12504                                         update[list[j]] = true;
12505                         }
12506                 }
12507         }
12508
12509         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12510
12511         if (debug)
12512         {
12513                 R_DrawDebugModel();
12514                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12515                 return;
12516         }
12517
12518         rsurface.lightmaptexture = NULL;
12519         rsurface.deluxemaptexture = NULL;
12520         rsurface.uselightmaptexture = false;
12521         rsurface.texture = NULL;
12522         rsurface.rtlight = NULL;
12523         numsurfacelist = 0;
12524         // add visible surfaces to draw list
12525         for (i = 0;i < model->nummodelsurfaces;i++)
12526         {
12527                 j = model->sortedmodelsurfaces[i];
12528                 if (r_refdef.viewcache.world_surfacevisible[j])
12529                         r_surfacelist[numsurfacelist++] = surfaces + j;
12530         }
12531         // update lightmaps if needed
12532         if (model->brushq1.firstrender)
12533         {
12534                 model->brushq1.firstrender = false;
12535                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12536                         if (update[j])
12537                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12538         }
12539         else if (update)
12540         {
12541                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12542                         if (r_refdef.viewcache.world_surfacevisible[j])
12543                                 if (update[j])
12544                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12545         }
12546         // don't do anything if there were no surfaces
12547         if (!numsurfacelist)
12548         {
12549                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12550                 return;
12551         }
12552         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12553
12554         // add to stats if desired
12555         if (r_speeds.integer && !skysurfaces && !depthonly)
12556         {
12557                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12558                 for (j = 0;j < numsurfacelist;j++)
12559                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12560         }
12561
12562         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12563 }
12564
12565 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12566 {
12567         int i, j, endj, flagsmask;
12568         dp_model_t *model = ent->model;
12569         msurface_t *surfaces;
12570         unsigned char *update;
12571         int numsurfacelist = 0;
12572         if (model == NULL)
12573                 return;
12574
12575         if (r_maxsurfacelist < model->num_surfaces)
12576         {
12577                 r_maxsurfacelist = model->num_surfaces;
12578                 if (r_surfacelist)
12579                         Mem_Free((msurface_t **)r_surfacelist);
12580                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12581         }
12582
12583         // if the model is static it doesn't matter what value we give for
12584         // wantnormals and wanttangents, so this logic uses only rules applicable
12585         // to a model, knowing that they are meaningless otherwise
12586         if (ent == r_refdef.scene.worldentity)
12587                 RSurf_ActiveWorldEntity();
12588         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12589                 RSurf_ActiveModelEntity(ent, false, false, false);
12590         else if (prepass)
12591                 RSurf_ActiveModelEntity(ent, true, true, true);
12592         else if (depthonly)
12593         {
12594                 switch (vid.renderpath)
12595                 {
12596                 case RENDERPATH_GL20:
12597                 case RENDERPATH_D3D9:
12598                 case RENDERPATH_D3D10:
12599                 case RENDERPATH_D3D11:
12600                 case RENDERPATH_SOFT:
12601                 case RENDERPATH_GLES2:
12602                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12603                         break;
12604                 case RENDERPATH_GL11:
12605                 case RENDERPATH_GL13:
12606                 case RENDERPATH_GLES1:
12607                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12608                         break;
12609                 }
12610         }
12611         else
12612         {
12613                 switch (vid.renderpath)
12614                 {
12615                 case RENDERPATH_GL20:
12616                 case RENDERPATH_D3D9:
12617                 case RENDERPATH_D3D10:
12618                 case RENDERPATH_D3D11:
12619                 case RENDERPATH_SOFT:
12620                 case RENDERPATH_GLES2:
12621                         RSurf_ActiveModelEntity(ent, true, true, false);
12622                         break;
12623                 case RENDERPATH_GL11:
12624                 case RENDERPATH_GL13:
12625                 case RENDERPATH_GLES1:
12626                         RSurf_ActiveModelEntity(ent, true, false, false);
12627                         break;
12628                 }
12629         }
12630
12631         surfaces = model->data_surfaces;
12632         update = model->brushq1.lightmapupdateflags;
12633
12634         // update light styles
12635         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12636         {
12637                 model_brush_lightstyleinfo_t *style;
12638                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12639                 {
12640                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12641                         {
12642                                 int *list = style->surfacelist;
12643                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12644                                 for (j = 0;j < style->numsurfaces;j++)
12645                                         update[list[j]] = true;
12646                         }
12647                 }
12648         }
12649
12650         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12651
12652         if (debug)
12653         {
12654                 R_DrawDebugModel();
12655                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12656                 return;
12657         }
12658
12659         rsurface.lightmaptexture = NULL;
12660         rsurface.deluxemaptexture = NULL;
12661         rsurface.uselightmaptexture = false;
12662         rsurface.texture = NULL;
12663         rsurface.rtlight = NULL;
12664         numsurfacelist = 0;
12665         // add visible surfaces to draw list
12666         for (i = 0;i < model->nummodelsurfaces;i++)
12667                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12668         // don't do anything if there were no surfaces
12669         if (!numsurfacelist)
12670         {
12671                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12672                 return;
12673         }
12674         // update lightmaps if needed
12675         if (update)
12676         {
12677                 int updated = 0;
12678                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12679                 {
12680                         if (update[j])
12681                         {
12682                                 updated++;
12683                                 R_BuildLightMap(ent, surfaces + j);
12684                         }
12685                 }
12686         }
12687
12688         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12689
12690         // add to stats if desired
12691         if (r_speeds.integer && !skysurfaces && !depthonly)
12692         {
12693                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12694                 for (j = 0;j < numsurfacelist;j++)
12695                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12696         }
12697
12698         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12699 }
12700
12701 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12702 {
12703         static texture_t texture;
12704         static msurface_t surface;
12705         const msurface_t *surfacelist = &surface;
12706
12707         // fake enough texture and surface state to render this geometry
12708
12709         texture.update_lastrenderframe = -1; // regenerate this texture
12710         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12711         texture.currentskinframe = skinframe;
12712         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12713         texture.offsetmapping = OFFSETMAPPING_OFF;
12714         texture.offsetscale = 1;
12715         texture.specularscalemod = 1;
12716         texture.specularpowermod = 1;
12717         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12718         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12719         // JUST GREP FOR "specularscalemod = 1".
12720
12721         surface.texture = &texture;
12722         surface.num_triangles = numtriangles;
12723         surface.num_firsttriangle = firsttriangle;
12724         surface.num_vertices = numvertices;
12725         surface.num_firstvertex = firstvertex;
12726
12727         // now render it
12728         rsurface.texture = R_GetCurrentTexture(surface.texture);
12729         rsurface.lightmaptexture = NULL;
12730         rsurface.deluxemaptexture = NULL;
12731         rsurface.uselightmaptexture = false;
12732         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12733 }
12734
12735 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)
12736 {
12737         static msurface_t surface;
12738         const msurface_t *surfacelist = &surface;
12739
12740         // fake enough texture and surface state to render this geometry
12741         surface.texture = texture;
12742         surface.num_triangles = numtriangles;
12743         surface.num_firsttriangle = firsttriangle;
12744         surface.num_vertices = numvertices;
12745         surface.num_firstvertex = firstvertex;
12746
12747         // now render it
12748         rsurface.texture = R_GetCurrentTexture(surface.texture);
12749         rsurface.lightmaptexture = NULL;
12750         rsurface.deluxemaptexture = NULL;
12751         rsurface.uselightmaptexture = false;
12752         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12753 }